From 28ab2e7a229600018c27513d49ef0aff08867d63 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 23 May 2023 17:24:39 +0200 Subject: [PATCH 001/180] [7.0] Bump to PHP 8.2 minimum --- Console/Descriptor/JsonDescriptor.php | 2 +- Console/Descriptor/MarkdownDescriptor.php | 2 +- Console/Descriptor/TextDescriptor.php | 2 +- Console/Descriptor/XmlDescriptor.php | 2 +- composer.json | 134 +++++++++++----------- 5 files changed, 71 insertions(+), 71 deletions(-) diff --git a/Console/Descriptor/JsonDescriptor.php b/Console/Descriptor/JsonDescriptor.php index 09e975ad4..81993fd59 100644 --- a/Console/Descriptor/JsonDescriptor.php +++ b/Console/Descriptor/JsonDescriptor.php @@ -370,7 +370,7 @@ private function getCallableData(mixed $callable): array } $data['name'] = $r->name; - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + if ($class = $r->getClosureCalledClass()) { $data['class'] = $class->name; if (!$r->getClosureThis()) { $data['static'] = true; diff --git a/Console/Descriptor/MarkdownDescriptor.php b/Console/Descriptor/MarkdownDescriptor.php index 1289c8ded..4304b3c05 100644 --- a/Console/Descriptor/MarkdownDescriptor.php +++ b/Console/Descriptor/MarkdownDescriptor.php @@ -393,7 +393,7 @@ protected function describeCallable(mixed $callable, array $options = []): void } $string .= "\n".sprintf('- Name: `%s`', $r->name); - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + if ($class = $r->getClosureCalledClass()) { $string .= "\n".sprintf('- Class: `%s`', $class->name); if (!$r->getClosureThis()) { $string .= "\n- Static: yes"; diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index 519d99f3a..e053b8c5e 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -615,7 +615,7 @@ private function formatCallable(mixed $callable): string if (str_contains($r->name, '{closure}')) { return 'Closure()'; } - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + if ($class = $r->getClosureCalledClass()) { return sprintf('%s::%s()', $class->name, $r->name); } diff --git a/Console/Descriptor/XmlDescriptor.php b/Console/Descriptor/XmlDescriptor.php index 79253d53f..2ff2fa14d 100644 --- a/Console/Descriptor/XmlDescriptor.php +++ b/Console/Descriptor/XmlDescriptor.php @@ -564,7 +564,7 @@ private function getCallableDocument(mixed $callable): \DOMDocument } $callableXML->setAttribute('name', $r->name); - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + if ($class = $r->getClosureCalledClass()) { $callableXML->setAttribute('class', $class->name); if (!$r->getClosureThis()) { $callableXML->setAttribute('static', 'true'); diff --git a/composer.json b/composer.json index 0fde32286..876681757 100644 --- a/composer.json +++ b/composer.json @@ -16,59 +16,59 @@ } ], "require": { - "php": ">=8.1", + "php": ">=8.2", "composer-runtime-api": ">=2.1", "ext-xml": "*", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.3|^7.0", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.1|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.3|^7.0", - "symfony/http-kernel": "^6.3|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0" }, "require-dev": { "doctrine/annotations": "^1.13.1|^2", "doctrine/persistence": "^1.3|^2|^3", - "symfony/asset": "^5.4|^6.0|^7.0", - "symfony/asset-mapper": "^6.3|^7.0", - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4.9|^6.0.9|^7.0", - "symfony/clock": "^6.2|^7.0", - "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/dom-crawler": "^6.3|^7.0", - "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/asset": "^6.4|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/dotenv": "^6.4|^7.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/form": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/html-sanitizer": "^6.1|^7.0", - "symfony/http-client": "^6.3|^7.0", - "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.2|^7.0", - "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", - "symfony/scheduler": "^6.3|^7.0", - "symfony/security-bundle": "^5.4|^6.0|^7.0", - "symfony/semaphore": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.3|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/string": "^5.4|^6.0|^7.0", - "symfony/translation": "^6.2.8|^7.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0", - "symfony/validator": "^6.3|^7.0", - "symfony/workflow": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0", - "symfony/property-info": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "symfony/web-link": "^5.4|^6.0|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/html-sanitizer": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/mailer": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/notifier": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/scheduler": "^6.4|^7.0", + "symfony/security-bundle": "^6.4|^7.0", + "symfony/semaphore": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/workflow": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "twig/twig": "^2.10|^3.0" }, @@ -78,29 +78,29 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "phpunit/phpunit": "<5.4.3", - "symfony/asset": "<5.4", - "symfony/clock": "<6.3", - "symfony/console": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/dom-crawler": "<6.3", - "symfony/http-client": "<6.3", - "symfony/form": "<5.4", - "symfony/lock": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<6.3", - "symfony/mime": "<6.2", - "symfony/property-info": "<5.4", - "symfony/property-access": "<5.4", - "symfony/serializer": "<6.3", - "symfony/security-csrf": "<5.4", - "symfony/security-core": "<5.4", - "symfony/stopwatch": "<5.4", - "symfony/translation": "<6.2.8", - "symfony/twig-bridge": "<5.4", - "symfony/twig-bundle": "<5.4", - "symfony/validator": "<6.3", - "symfony/web-profiler-bundle": "<5.4", - "symfony/workflow": "<5.4" + "symfony/asset": "<6.4", + "symfony/clock": "<6.4", + "symfony/console": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/dom-crawler": "<6.4", + "symfony/http-client": "<6.4", + "symfony/form": "<6.4", + "symfony/lock": "<6.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/property-info": "<6.4", + "symfony/property-access": "<6.4", + "symfony/serializer": "<6.4", + "symfony/security-csrf": "<6.4", + "symfony/security-core": "<6.4", + "symfony/stopwatch": "<6.4", + "symfony/translation": "<6.4", + "symfony/twig-bridge": "<6.4", + "symfony/twig-bundle": "<6.4", + "symfony/validator": "<6.4", + "symfony/web-profiler-bundle": "<6.4", + "symfony/workflow": "<6.4" }, "autoload": { "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, From b2166d2abcddd8d34f97b60f60d0cc466674e0c7 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 6 Jun 2023 15:19:43 +0200 Subject: [PATCH 002/180] [DependencyInjection] Remove deprecations across the component --- Console/Application.php | 10 +-- Controller/ControllerResolver.php | 5 -- Tests/Controller/ControllerResolverTest.php | 82 --------------------- 3 files changed, 1 insertion(+), 96 deletions(-) diff --git a/Console/Application.php b/Console/Application.php index 02709ba64..0451b31fe 100644 --- a/Console/Application.php +++ b/Console/Application.php @@ -19,7 +19,6 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; @@ -112,14 +111,7 @@ public function get(string $name): Command { $this->registerCommands(); - $command = parent::get($name); - - if ($command instanceof ContainerAwareInterface) { - trigger_deprecation('symfony/dependency-injection', '6.4', 'Relying on "%s" to get the container in "%s" is deprecated, register the command as a service and use dependency injection instead.', ContainerAwareInterface::class, get_debug_type($command)); - $command->setContainer($this->kernel->getContainer()); - } - - return $command; + return parent::get($name); } public function all(string $namespace = null): array diff --git a/Controller/ControllerResolver.php b/Controller/ControllerResolver.php index 3449740bf..af8b49429 100644 --- a/Controller/ControllerResolver.php +++ b/Controller/ControllerResolver.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Controller; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; /** @@ -25,10 +24,6 @@ protected function instantiateController(string $class): object { $controller = parent::instantiateController($class); - if ($controller instanceof ContainerAwareInterface) { - trigger_deprecation('symfony/dependency-injection', '6.4', 'Relying on "%s" to get the container in "%s" is deprecated, register the controller as a service and use dependency injection instead.', ContainerAwareInterface::class, get_debug_type($controller)); - $controller->setContainer($this->container); - } 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)); diff --git a/Tests/Controller/ControllerResolverTest.php b/Tests/Controller/ControllerResolverTest.php index 5488111ee..0c51924a4 100644 --- a/Tests/Controller/ControllerResolverTest.php +++ b/Tests/Controller/ControllerResolverTest.php @@ -13,74 +13,15 @@ use Psr\Container\ContainerInterface as Psr11ContainerInterface; use Psr\Log\LoggerInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest; class ControllerResolverTest extends ContainerControllerResolverTest { - use ExpectDeprecationTrait; - - /** - * @group legacy - */ - public function testGetControllerOnContainerAware() - { - $resolver = $this->createControllerResolver(); - $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController::testAction'); - - $this->expectDeprecation('Since symfony/dependency-injection 6.4: Relying on "Symfony\Component\DependencyInjection\ContainerAwareInterface" to get the container in "Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController" is deprecated, register the controller as a service and use dependency injection instead.'); - $controller = $resolver->getController($request); - - $this->assertInstanceOf(ContainerAwareController::class, $controller[0]); - $this->assertInstanceOf(ContainerInterface::class, $controller[0]->getContainer()); - $this->assertSame('testAction', $controller[1]); - } - - /** - * @group legacy - */ - public function testGetControllerOnContainerAwareInvokable() - { - $resolver = $this->createControllerResolver(); - $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController'); - - $this->expectDeprecation('Since symfony/dependency-injection 6.4: Relying on "Symfony\Component\DependencyInjection\ContainerAwareInterface" to get the container in "Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController" is deprecated, register the controller as a service and use dependency injection instead.'); - $controller = $resolver->getController($request); - - $this->assertInstanceOf(ContainerAwareController::class, $controller); - $this->assertInstanceOf(ContainerInterface::class, $controller->getContainer()); - } - - /** - * @group legacy - */ - public function testContainerAwareControllerGetsContainerWhenNotSet() - { - class_exists(AbstractControllerTest::class); - - $controller = new ContainerAwareController(); - - $container = new Container(); - $container->set(TestAbstractController::class, $controller); - - $resolver = $this->createControllerResolver(null, $container); - - $request = Request::create('/'); - $request->attributes->set('_controller', TestAbstractController::class.'::testAction'); - - $this->expectDeprecation('Since symfony/dependency-injection 6.4: Relying on "Symfony\Component\DependencyInjection\ContainerAwareInterface" to get the container in "Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController" is deprecated, register the controller as a service and use dependency injection instead.'); - $this->assertSame([$controller, 'testAction'], $resolver->getController($request)); - $this->assertSame($container, $controller->getContainer()); - } - public function testAbstractControllerGetsContainerWhenNotSet() { $this->expectException(\LogicException::class); @@ -183,29 +124,6 @@ protected function createMockContainer() } } -class ContainerAwareController implements ContainerAwareInterface -{ - private ?ContainerInterface $container = null; - - public function setContainer(?ContainerInterface $container): void - { - $this->container = $container; - } - - public function getContainer(): ?ContainerInterface - { - return $this->container; - } - - public function testAction() - { - } - - public function __invoke() - { - } -} - class DummyController extends AbstractController { public function getContainer(): Psr11ContainerInterface From 4694cf6431933394449e914a0d6543670eff8331 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sun, 2 Jul 2023 13:49:44 +0200 Subject: [PATCH 003/180] [Bridges][Bundles] Convert to native return types --- Command/AbstractConfigCommand.php | 10 ++-------- Console/Application.php | 10 ++-------- .../Compiler/AddDebugLogProcessorPass.php | 10 ++-------- .../AddExpressionLanguageProvidersPass.php | 5 +---- .../Compiler/AssetsContextPass.php | 5 +---- .../Compiler/ContainerBuilderDebugDumpPass.php | 5 +---- .../Compiler/DataCollectorTranslatorPass.php | 5 +---- .../Compiler/LoggingTranslatorPass.php | 5 +---- DependencyInjection/Compiler/ProfilerPass.php | 5 +---- ...moveUnusedSessionMarshallingHandlerPass.php | 5 +---- .../TestServiceContainerRealRefPass.php | 5 +---- .../TestServiceContainerWeakRefPass.php | 5 +---- .../Compiler/UnusedTagsPass.php | 5 +---- .../Compiler/WorkflowGuardListenerPass.php | 5 +---- DependencyInjection/FrameworkExtension.php | 4 +--- FrameworkBundle.php | 10 ++-------- Kernel/MicroKernelTrait.php | 5 +---- KernelBrowser.php | 18 +++--------------- Routing/AnnotatedRouteControllerLoader.php | 4 +--- Secrets/AbstractVault.php | 5 +---- Test/KernelTestCase.php | 4 +--- Translation/Translator.php | 15 +++------------ 22 files changed, 30 insertions(+), 120 deletions(-) diff --git a/Command/AbstractConfigCommand.php b/Command/AbstractConfigCommand.php index 94b95e502..479bbfe6a 100644 --- a/Command/AbstractConfigCommand.php +++ b/Command/AbstractConfigCommand.php @@ -28,10 +28,7 @@ */ abstract class AbstractConfigCommand extends ContainerDebugCommand { - /** - * @return void - */ - protected function listBundles(OutputInterface|StyleInterface $output) + protected function listBundles(OutputInterface|StyleInterface $output): void { $title = 'Available registered bundles with their extension alias if available'; $headers = ['Bundle name', 'Extension alias']; @@ -159,10 +156,7 @@ protected function findExtension(string $name): ExtensionInterface throw new LogicException($message); } - /** - * @return void - */ - public function validateConfiguration(ExtensionInterface $extension, mixed $configuration) + public function validateConfiguration(ExtensionInterface $extension, mixed $configuration): void { if (!$configuration) { throw new \LogicException(sprintf('The extension with alias "%s" does not have its getConfiguration() method setup.', $extension->getAlias())); diff --git a/Console/Application.php b/Console/Application.php index 0451b31fe..80a2f4935 100644 --- a/Console/Application.php +++ b/Console/Application.php @@ -51,10 +51,7 @@ public function getKernel(): KernelInterface return $this->kernel; } - /** - * @return void - */ - public function reset() + public function reset(): void { if ($this->kernel->getContainer()->has('services_resetter')) { $this->kernel->getContainer()->get('services_resetter')->reset(); @@ -133,10 +130,7 @@ public function add(Command $command): ?Command return parent::add($command); } - /** - * @return void - */ - protected function registerCommands() + protected function registerCommands(): void { if ($this->commandsRegistered) { return; diff --git a/DependencyInjection/Compiler/AddDebugLogProcessorPass.php b/DependencyInjection/Compiler/AddDebugLogProcessorPass.php index d0aca7a06..5c8a470c1 100644 --- a/DependencyInjection/Compiler/AddDebugLogProcessorPass.php +++ b/DependencyInjection/Compiler/AddDebugLogProcessorPass.php @@ -17,10 +17,7 @@ class AddDebugLogProcessorPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('profiler')) { return; @@ -37,10 +34,7 @@ public function process(ContainerBuilder $container) $definition->addMethodCall('pushProcessor', [new Reference('debug.log_processor')]); } - /** - * @return void - */ - public static function configureLogger(mixed $logger) + public static function configureLogger(mixed $logger): void { if (\is_object($logger) && method_exists($logger, 'removeDebugLogger') && \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { $logger->removeDebugLogger(); diff --git a/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php index 5442b2773..c816ef403 100644 --- a/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php +++ b/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php @@ -22,10 +22,7 @@ */ class AddExpressionLanguageProvidersPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { // routing if ($container->has('router.default')) { diff --git a/DependencyInjection/Compiler/AssetsContextPass.php b/DependencyInjection/Compiler/AssetsContextPass.php index e8c2ad3a0..c4b99c568 100644 --- a/DependencyInjection/Compiler/AssetsContextPass.php +++ b/DependencyInjection/Compiler/AssetsContextPass.php @@ -18,10 +18,7 @@ class AssetsContextPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('assets.context')) { return; diff --git a/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php b/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php index 1e08ef314..e4023e623 100644 --- a/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php +++ b/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php @@ -25,10 +25,7 @@ */ class ContainerBuilderDebugDumpPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->getParameter('debug.container.dump')) { return; diff --git a/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/DependencyInjection/Compiler/DataCollectorTranslatorPass.php index e66e98b45..c6730ceb0 100644 --- a/DependencyInjection/Compiler/DataCollectorTranslatorPass.php +++ b/DependencyInjection/Compiler/DataCollectorTranslatorPass.php @@ -20,10 +20,7 @@ */ class DataCollectorTranslatorPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->has('translator')) { return; diff --git a/DependencyInjection/Compiler/LoggingTranslatorPass.php b/DependencyInjection/Compiler/LoggingTranslatorPass.php index b7cb920bf..3f4a3926c 100644 --- a/DependencyInjection/Compiler/LoggingTranslatorPass.php +++ b/DependencyInjection/Compiler/LoggingTranslatorPass.php @@ -22,10 +22,7 @@ */ class LoggingTranslatorPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) { return; diff --git a/DependencyInjection/Compiler/ProfilerPass.php b/DependencyInjection/Compiler/ProfilerPass.php index c2d669fe1..68ee76d4b 100644 --- a/DependencyInjection/Compiler/ProfilerPass.php +++ b/DependencyInjection/Compiler/ProfilerPass.php @@ -24,10 +24,7 @@ */ class ProfilerPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (false === $container->hasDefinition('profiler')) { return; diff --git a/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php b/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php index fedc30d06..7f0ec5f89 100644 --- a/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php +++ b/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php @@ -19,10 +19,7 @@ */ class RemoveUnusedSessionMarshallingHandlerPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('session.marshalling_handler')) { return; diff --git a/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php b/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php index aed3b1340..68a6ee103 100644 --- a/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php +++ b/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php @@ -21,10 +21,7 @@ */ class TestServiceContainerRealRefPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('test.private_services_locator')) { return; diff --git a/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php b/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php index 6e7669a71..3b3dfcc06 100644 --- a/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php +++ b/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php @@ -21,10 +21,7 @@ */ class TestServiceContainerWeakRefPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('test.private_services_locator')) { return; diff --git a/DependencyInjection/Compiler/UnusedTagsPass.php b/DependencyInjection/Compiler/UnusedTagsPass.php index b04516410..ae5daac8e 100644 --- a/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/DependencyInjection/Compiler/UnusedTagsPass.php @@ -105,10 +105,7 @@ class UnusedTagsPass implements CompilerPassInterface 'workflow', ]; - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { $tags = array_unique(array_merge($container->findTags(), self::KNOWN_TAGS)); diff --git a/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/DependencyInjection/Compiler/WorkflowGuardListenerPass.php index bda9ca951..394628c5d 100644 --- a/DependencyInjection/Compiler/WorkflowGuardListenerPass.php +++ b/DependencyInjection/Compiler/WorkflowGuardListenerPass.php @@ -21,10 +21,7 @@ */ class WorkflowGuardListenerPass implements CompilerPassInterface { - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasParameter('workflow.has_guard_listeners')) { return; diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index cb855a9c2..4b79ab736 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -207,11 +207,9 @@ class FrameworkExtension extends Extension /** * Responds to the app.config configuration parameter. * - * @return void - * * @throws LogicException */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config')); diff --git a/FrameworkBundle.php b/FrameworkBundle.php index 339b28e83..fa289c683 100644 --- a/FrameworkBundle.php +++ b/FrameworkBundle.php @@ -90,10 +90,7 @@ class_exists(Registry::class); */ class FrameworkBundle extends Bundle { - /** - * @return void - */ - public function boot() + public function boot(): void { $_ENV['DOCTRINE_DEPRECATIONS'] = $_SERVER['DOCTRINE_DEPRECATIONS'] ??= 'trigger'; @@ -115,10 +112,7 @@ public function boot() } } - /** - * @return void - */ - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { parent::build($container); diff --git a/Kernel/MicroKernelTrait.php b/Kernel/MicroKernelTrait.php index f82e1fb20..878c36af7 100644 --- a/Kernel/MicroKernelTrait.php +++ b/Kernel/MicroKernelTrait.php @@ -129,10 +129,7 @@ public function registerBundles(): iterable } } - /** - * @return void - */ - public function registerContainerConfiguration(LoaderInterface $loader) + public function registerContainerConfiguration(LoaderInterface $loader): void { $loader->load(function (ContainerBuilder $container) use ($loader) { $container->loadFromExtension('framework', [ diff --git a/KernelBrowser.php b/KernelBrowser.php index 0379be8f5..694714faa 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -39,9 +39,6 @@ public function __construct(KernelInterface $kernel, array $server = [], History parent::__construct($kernel, $server, $history, $cookieJar); } - /** - * Returns the container. - */ public function getContainer(): ContainerInterface { $container = $this->kernel->getContainer(); @@ -49,9 +46,6 @@ public function getContainer(): ContainerInterface return $container->has('test.service_container') ? $container->get('test.service_container') : $container; } - /** - * Returns the kernel. - */ public function getKernel(): KernelInterface { return $this->kernel; @@ -73,10 +67,8 @@ public function getProfile(): HttpProfile|false|null * Enables the profiler for the very next request. * * If the profiler is not enabled, the call to this method does nothing. - * - * @return void */ - public function enableProfiler() + public function enableProfiler(): void { if ($this->getContainer()->has('profiler')) { $this->profiler = true; @@ -88,20 +80,16 @@ public function enableProfiler() * * By default, the Client reboots the Kernel for each request. This method * allows to keep the same kernel across requests. - * - * @return void */ - public function disableReboot() + public function disableReboot(): void { $this->reboot = false; } /** * Enables kernel reboot between requests. - * - * @return void */ - public function enableReboot() + public function enableReboot(): void { $this->reboot = true; } diff --git a/Routing/AnnotatedRouteControllerLoader.php b/Routing/AnnotatedRouteControllerLoader.php index ec03f8497..ac760405c 100644 --- a/Routing/AnnotatedRouteControllerLoader.php +++ b/Routing/AnnotatedRouteControllerLoader.php @@ -24,10 +24,8 @@ class AnnotatedRouteControllerLoader extends AnnotationClassLoader { /** * Configures the _controller default parameter of a given Route instance. - * - * @return void */ - protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot) + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot): void { if ('__invoke' === $method->getName()) { $route->setDefault('_controller', $class->getName()); diff --git a/Secrets/AbstractVault.php b/Secrets/AbstractVault.php index b3eb0c6bc..ac2078f6d 100644 --- a/Secrets/AbstractVault.php +++ b/Secrets/AbstractVault.php @@ -40,10 +40,7 @@ protected function validateName(string $name): void } } - /** - * @return string - */ - protected function getPrettyPath(string $path) + protected function getPrettyPath(string $path): string { return str_replace(getcwd().\DIRECTORY_SEPARATOR, '', $path); } diff --git a/Test/KernelTestCase.php b/Test/KernelTestCase.php index bb5560a7b..639214a43 100644 --- a/Test/KernelTestCase.php +++ b/Test/KernelTestCase.php @@ -84,10 +84,8 @@ protected static function bootKernel(array $options = []): KernelInterface * used by other services. * * Using this method is the best way to get a container from your test code. - * - * @return Container */ - protected static function getContainer(): ContainerInterface + protected static function getContainer(): Container { if (!static::$booted) { static::bootKernel(); diff --git a/Translation/Translator.php b/Translation/Translator.php index dac3b6394..3cce60ec1 100644 --- a/Translation/Translator.php +++ b/Translation/Translator.php @@ -118,10 +118,7 @@ public function warmUp(string $cacheDir): array return []; } - /** - * @return void - */ - public function addResource(string $format, mixed $resource, string $locale, string $domain = null) + public function addResource(string $format, mixed $resource, string $locale, string $domain = null): void { if ($this->resourceFiles) { $this->addResourceFiles(); @@ -129,10 +126,7 @@ public function addResource(string $format, mixed $resource, string $locale, str $this->resources[] = [$format, $resource, $locale, $domain]; } - /** - * @return void - */ - protected function initializeCatalogue(string $locale) + protected function initializeCatalogue(string $locale): void { $this->initialize(); parent::initializeCatalogue($locale); @@ -151,10 +145,7 @@ protected function doLoadCatalogue(string $locale): void } } - /** - * @return void - */ - protected function initialize() + protected function initialize(): void { if ($this->resourceFiles) { $this->addResourceFiles(); From 894b1be3e34b27004d1134623db1752b7b127351 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 3 Jul 2023 15:44:01 +0200 Subject: [PATCH 004/180] - --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e59213f5..effe9a430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Remove command `translation:update`, use `translation:extract` instead + 6.3 --- From 008116925e2f07b6b929d6f9ad5f1b95df86eeec Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 30 Jun 2023 18:53:02 +0200 Subject: [PATCH 005/180] Remove BC layers related to new methods and new parameters --- CHANGELOG.md | 5 +++++ Command/TranslationUpdateCommand.php | 4 ---- Tests/Command/TranslationUpdateCommandTest.php | 8 -------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e59213f5..effe9a430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Remove command `translation:update`, use `translation:extract` instead + 6.3 --- diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index 15c536ea9..f49849d4d 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -127,10 +127,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io = new SymfonyStyle($input, $output); $errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io; - if ('translation:update' === $input->getFirstArgument()) { - $errorIo->caution('Command "translation:update" is deprecated since version 5.4 and will be removed in Symfony 6.0. Use "translation:extract" instead.'); - } - $io = new SymfonyStyle($input, $output); $errorIo = $io->getErrorStyle(); diff --git a/Tests/Command/TranslationUpdateCommandTest.php b/Tests/Command/TranslationUpdateCommandTest.php index f883fac0c..89e983d4e 100644 --- a/Tests/Command/TranslationUpdateCommandTest.php +++ b/Tests/Command/TranslationUpdateCommandTest.php @@ -29,14 +29,6 @@ class TranslationUpdateCommandTest extends TestCase private $fs; private $translationDir; - public function testDumpMessagesAndCleanWithDeprecatedCommandName() - { - $tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]); - $tester->execute(['command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true]); - $this->assertMatchesRegularExpression('/foo/', $tester->getDisplay()); - $this->assertMatchesRegularExpression('/1 message was successfully extracted/', $tester->getDisplay()); - } - public function testDumpMessagesAndClean() { $tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]); From 58c5dca4e674576ac473d5ac17a771732ce05725 Mon Sep 17 00:00:00 2001 From: Frank Fiebig Date: Tue, 4 Jul 2023 11:21:50 +0200 Subject: [PATCH 006/180] [Lock] 7.0 remove deprecations in Lock Component --- DependencyInjection/FrameworkExtension.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 4b79ab736..f5ddf2fac 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -95,7 +95,6 @@ use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\Controller\ValueResolverInterface; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -596,8 +595,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('container.service_locator'); $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) ->addTag('container.service_subscriber'); - $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) - ->addTag('controller.argument_value_resolver'); $container->registerForAutoconfiguration(ValueResolverInterface::class) ->addTag('controller.argument_value_resolver'); $container->registerForAutoconfiguration(AbstractController::class) From 7f96ac7269dda50bc93f589aa973a82cf73a9a80 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 4 Jul 2023 14:50:59 +0200 Subject: [PATCH 007/180] [7.0] Remove remaining deprecated code paths --- CHANGELOG.md | 6 +++ Command/WorkflowDumpCommand.php | 48 ++++------------- Controller/AbstractController.php | 16 +----- DependencyInjection/Configuration.php | 46 +--------------- DependencyInjection/FrameworkExtension.php | 45 +--------------- KernelBrowser.php | 4 -- Resources/config/annotations.php | 2 +- Resources/config/http_client.php | 2 - Resources/config/mailer_transports.php | 5 -- Resources/config/messenger.php | 3 -- Resources/config/notifier.php | 3 -- Resources/config/schema/symfony-1.0.xsd | 30 ++--------- Resources/config/serializer.php | 7 --- Resources/config/translation.php | 5 -- Resources/config/workflow.php | 4 -- Tests/Controller/AbstractControllerTest.php | 52 ------------------- .../DependencyInjection/ConfigurationTest.php | 1 - ...ssenger_with_disabled_reset_on_message.php | 20 ------- ...r_with_explict_reset_on_message_legacy.php | 20 ------- .../Fixtures/xml/exceptions_legacy.xml | 16 ------ ...ssenger_with_disabled_reset_on_message.xml | 22 -------- ...r_with_explict_reset_on_message_legacy.xml | 22 -------- .../FrameworkExtensionTestCase.php | 36 +------------ .../XmlFrameworkExtensionTest.php | 34 ------------ composer.json | 1 - 25 files changed, 23 insertions(+), 427 deletions(-) delete mode 100644 Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php delete mode 100644 Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php delete mode 100644 Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml delete mode 100644 Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml delete mode 100644 Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index effe9a430..79c157980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ CHANGELOG --- * Remove command `translation:update`, use `translation:extract` instead + * Make the `http_method_override` config option default to `false` + * Remove `AbstractController::renderForm()`, use `render()` instead + * Remove the `Symfony\Component\Serializer\Normalizer\ObjectNormalizer` and + `Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against + `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead + * Remove the `Http\Client\HttpClient` service, use `Psr\Http\Client\ClientInterface` instead 6.3 --- diff --git a/Command/WorkflowDumpCommand.php b/Command/WorkflowDumpCommand.php index f84a560c6..f69a0e11e 100644 --- a/Command/WorkflowDumpCommand.php +++ b/Command/WorkflowDumpCommand.php @@ -21,7 +21,6 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\Dumper\GraphvizDumper; use Symfony\Component\Workflow\Dumper\MermaidDumper; use Symfony\Component\Workflow\Dumper\PlantUmlDumper; @@ -37,33 +36,16 @@ #[AsCommand(name: 'workflow:dump', description: 'Dump a workflow')] class WorkflowDumpCommand extends Command { - /** - * string is the service id. - * - * @var array - */ - private array $definitions = []; - - private ServiceLocator $workflows; - private const DUMP_FORMAT_OPTIONS = [ 'puml', 'mermaid', 'dot', ]; - public function __construct($workflows) - { + public function __construct( + private ServiceLocator $workflows, + ) { parent::__construct(); - - if ($workflows instanceof ServiceLocator) { - $this->workflows = $workflows; - } elseif (\is_array($workflows)) { - $this->definitions = $workflows; - trigger_deprecation('symfony/framework-bundle', '6.2', 'Passing an array of definitions in "%s()" is deprecated. Inject a ServiceLocator filled with all workflows instead.', __METHOD__); - } else { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an array or a ServiceLocator, "%s" given.', __METHOD__, \gettype($workflows))); - } } protected function configure(): void @@ -92,20 +74,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $workflowName = $input->getArgument('name'); - if (isset($this->workflows)) { - if (!$this->workflows->has($workflowName)) { - throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName)); - } - $workflow = $this->workflows->get($workflowName); - $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; - $definition = $workflow->getDefinition(); - } elseif (isset($this->definitions['workflow.'.$workflowName])) { - $definition = $this->definitions['workflow.'.$workflowName]; - $type = 'workflow'; - } elseif (isset($this->definitions['state_machine.'.$workflowName])) { - $definition = $this->definitions['state_machine.'.$workflowName]; - $type = 'state_machine'; + if (!$this->workflows->has($workflowName)) { + throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName)); } + $workflow = $this->workflows->get($workflowName); + $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; + $definition = $workflow->getDefinition(); if (null === $definition) { throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName)); @@ -147,11 +121,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestArgumentValuesFor('name')) { - if (isset($this->workflows)) { - $suggestions->suggestValues(array_keys($this->workflows->getProvidedServices())); - } else { - $suggestions->suggestValues(array_keys($this->definitions)); - } + $suggestions->suggestValues(array_keys($this->workflows->getProvidedServices())); } if ($input->mustSuggestOptionValuesFor('dump-format')) { diff --git a/Controller/AbstractController.php b/Controller/AbstractController.php index 13e155235..4af31ad7d 100644 --- a/Controller/AbstractController.php +++ b/Controller/AbstractController.php @@ -186,7 +186,7 @@ protected function addFlash(string $type, mixed $message): void } if (!$session instanceof FlashBagAwareSessionInterface) { - trigger_deprecation('symfony/framework-bundle', '6.2', 'Calling "addFlash()" method when the session does not implement %s is deprecated.', FlashBagAwareSessionInterface::class); + throw new \LogicException(sprintf('You cannot use the addFlash method because class "%s" doesn\'t implement "%s".', get_debug_type($session), FlashBagAwareSessionInterface::class)); } $session->getFlashBag()->add($type, $message); @@ -268,20 +268,6 @@ protected function render(string $view, array $parameters = [], Response $respon return $response; } - /** - * Renders a view and sets the appropriate status code when a form is listed in parameters. - * - * If an invalid form is found in the list of parameters, a 422 status code is returned. - * - * @deprecated since Symfony 6.2, use render() instead - */ - protected function renderForm(string $view, array $parameters = [], Response $response = null): Response - { - trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s::renderForm()" method is deprecated, use "render()" instead.', get_debug_type($this)); - - return $this->render($view, $parameters, $response); - } - /** * Streams a view. */ diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 708b43b84..8ca6a54c0 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -81,23 +81,12 @@ public function getConfigTreeBuilder(): TreeBuilder return $v; }) ->end() - ->validate() - ->always(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.'); - - $v['http_method_override'] = true; - } - - return $v; - }) - ->end() ->fixXmlConfig('enabled_locale') ->children() ->scalarNode('secret')->end() ->booleanNode('http_method_override') ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") - ->treatNullLike(false) + ->defaultFalse() ->end() ->scalarNode('trust_x_sendfile_type_header') ->info('Set true to enable support for xsendfile in binary file responses.') @@ -244,9 +233,6 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->scalarNode('field_name')->defaultValue('_token')->end() ->end() ->end() - ->booleanNode('legacy_error_messages') - ->setDeprecated('symfony/framework-bundle', '6.2') - ->end() ->end() ->end() ->end() @@ -1303,27 +1289,6 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode): void ->arrayNode('exceptions') ->info('Exception handling configuration') ->useAttributeAsKey('class') - ->beforeNormalization() - // Handle legacy XML configuration - ->ifArray() - ->then(function (array $v): array { - if (!\array_key_exists('exception', $v)) { - return $v; - } - - trigger_deprecation('symfony/framework-bundle', '6.3', '"framework:exceptions" tag is deprecated. Unwrap it and replace your "framework:exception" tags\' "name" attribute by "class".'); - - $v = $v['exception']; - unset($v['exception']); - - foreach ($v as &$exception) { - $exception['class'] = $exception['name']; - unset($exception['name']); - } - - return $v; - }) - ->end() ->prototype('array') ->children() ->scalarNode('log_level') @@ -1620,15 +1585,6 @@ function ($a) { ->defaultNull() ->info('Transport name to send failed messages to (after all retries have failed).') ->end() - ->booleanNode('reset_on_message') - ->defaultTrue() - ->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(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() ->arrayNode('stop_worker_on_signals') ->defaultValue([]) ->info('A list of signals that should stop the worker; defaults to SIGTERM and SIGINT.') diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index f5ddf2fac..34e8c93b9 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -111,7 +111,6 @@ use Symfony\Component\Messenger\Bridge as MessengerBridge; use Symfony\Component\Messenger\Command\StatsCommand; use Symfony\Component\Messenger\Handler\BatchHandlerInterface; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; @@ -213,7 +212,7 @@ public function load(array $configs, ContainerBuilder $container): void $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config')); if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled('symfony/symfony') && 'symfony/symfony' !== (InstalledVersions::getRootPackage()['name'] ?? '')) { - trigger_deprecation('symfony/symfony', '6.1', 'Requiring the "symfony/symfony" package is deprecated; replace it with standalone components instead.'); + throw new \LogicException('Requiring the "symfony/symfony" package is unsupported; replace it with standalone components instead.'); } $loader->load('web.php'); @@ -647,8 +646,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('validator.constraint_validator'); $container->registerForAutoconfiguration(ObjectInitializerInterface::class) ->addTag('validator.initializer'); - $container->registerForAutoconfiguration(MessageHandlerInterface::class) - ->addTag('messenger.message_handler'); $container->registerForAutoconfiguration(BatchHandlerInterface::class) ->addTag('messenger.message_handler'); $container->registerForAutoconfiguration(MessengerTransportFactoryInterface::class) @@ -2591,7 +2588,6 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Mailjet\Transport\MailjetTransportFactory::class => 'mailer.transport_factory.mailjet', MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', - MailerBridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', MailerBridge\Sendinblue\Transport\SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', @@ -2893,45 +2889,6 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde } } - /** - * @deprecated since Symfony 6.2 - * - * @return void - */ - public static function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig) - { - trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s()" method is deprecated.', __METHOD__); - - // default configuration (when used by other DI extensions) - $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter']; - - $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')); - - if (null !== $limiterConfig['lock_factory']) { - if (!interface_exists(LockInterface::class)) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name)); - } - if (!$container->hasDefinition('lock.factory.abstract')) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be configured.', $name)); - } - - $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory'])); - } - unset($limiterConfig['lock_factory']); - - if (null === $storageId = $limiterConfig['storage_service'] ?? null) { - $container->register($storageId = 'limiter.storage.'.$name, CacheStorage::class)->addArgument(new Reference($limiterConfig['cache_pool'])); - } - - $limiter->replaceArgument(1, new Reference($storageId)); - unset($limiterConfig['storage_service'], $limiterConfig['cache_pool']); - - $limiterConfig['id'] = $name; - $limiter->replaceArgument(0, $limiterConfig); - - $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter'); - } - private function registerUidConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void { $loader->load('uid.php'); diff --git a/KernelBrowser.php b/KernelBrowser.php index 694714faa..794f4f454 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -110,10 +110,6 @@ public function loginUser(object $user, string $firewallContext = 'main'): stati } $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); - // required for compatibility with Symfony 5.4 - if (method_exists($token, 'isAuthenticated')) { - $token->setAuthenticated(true, false); - } $container = $this->getContainer(); $container->get('security.untracked_token_storage')->setToken($token); diff --git a/Resources/config/annotations.php b/Resources/config/annotations.php index f043c87ec..0f561d9d3 100644 --- a/Resources/config/annotations.php +++ b/Resources/config/annotations.php @@ -22,7 +22,7 @@ return static function (ContainerConfigurator $container) { $container->services() ->set('annotations.reader', AnnotationReader::class) - ->call('addGlobalIgnoredName', ['required']) // @deprecated since Symfony 6.3 + ->call('addGlobalIgnoredName', ['required']) ->set('annotations.cached_reader', PsrCachedReader::class) ->args([ diff --git a/Resources/config/http_client.php b/Resources/config/http_client.php index 23b794f45..ed932fdf8 100644 --- a/Resources/config/http_client.php +++ b/Resources/config/http_client.php @@ -58,8 +58,6 @@ ]) ->alias(HttpAsyncClient::class, 'httplug.http_client') - ->alias(\Http\Client\HttpClient::class, 'httplug.http_client') - ->deprecate('symfony/framework-bundle', '6.3', 'The "%alias_id%" service is deprecated, use "'.ClientInterface::class.'" instead.') ->set('http_client.abstract_retry_strategy', GenericRetryStrategy::class) ->abstract() diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index d352eb5be..bc5900a76 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -19,7 +19,6 @@ use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -92,10 +91,6 @@ ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.ohmysmtp', OhMySmtpTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class) ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory', ['priority' => -100]) diff --git a/Resources/config/messenger.php b/Resources/config/messenger.php index 3fe593ac6..0096ff1e0 100644 --- a/Resources/config/messenger.php +++ b/Resources/config/messenger.php @@ -209,9 +209,6 @@ ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'messenger']) - ->alias('messenger.listener.stop_worker_on_sigterm_signal_listener', 'messenger.listener.stop_worker_signals_listener') - ->deprecate('6.3', 'symfony/messenger', 'The "%alias_id%" service is deprecated, use "messenger.listener.stop_worker_signals_listener" instead.') - ->set('messenger.listener.stop_worker_on_stop_exception_listener', StopWorkerOnCustomStopExceptionListener::class) ->tag('kernel.event_subscriber') diff --git a/Resources/config/notifier.php b/Resources/config/notifier.php index 6ce674148..3bd19b8dd 100644 --- a/Resources/config/notifier.php +++ b/Resources/config/notifier.php @@ -129,8 +129,5 @@ ->set('notifier.notification_logger_listener', NotificationLoggerListener::class) ->tag('kernel.event_subscriber') - ->alias('notifier.logger_notification_listener', 'notifier.notification_logger_listener') - ->deprecate('symfony/framework-bundle', '6.3', 'The "%alias_id%" service is deprecated, use "notifier.notification_logger_listener" instead.') - ; }; diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index a2abb5bc0..69475e307 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -31,8 +31,7 @@ - - + @@ -67,7 +66,6 @@ - @@ -409,31 +407,10 @@ - - - - - - - + - - - - - - - - - - - - - - - - + @@ -585,7 +562,6 @@ - diff --git a/Resources/config/serializer.php b/Resources/config/serializer.php index 6459dfa44..94107237f 100644 --- a/Resources/config/serializer.php +++ b/Resources/config/serializer.php @@ -42,7 +42,6 @@ use Symfony\Component\Serializer\Normalizer\FormErrorNormalizer; use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Serializer\Normalizer\MimeMessageNormalizer; -use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ProblemNormalizer; @@ -127,9 +126,6 @@ ]) ->tag('serializer.normalizer', ['priority' => -1000]) - ->alias(ObjectNormalizer::class, 'serializer.normalizer.object') - ->deprecate('symfony/serializer', '6.2', 'The "%alias_id%" service alias is deprecated, type-hint against "'.NormalizerInterface::class.'" or implement "'.NormalizerAwareInterface::class.'" instead.') - ->set('serializer.normalizer.property', PropertyNormalizer::class) ->args([ service('serializer.mapping.class_metadata_factory'), @@ -139,9 +135,6 @@ null, ]) - ->alias(PropertyNormalizer::class, 'serializer.normalizer.property') - ->deprecate('symfony/serializer', '6.2', 'The "%alias_id%" service alias is deprecated, type-hint against "'.NormalizerInterface::class.'" or implement "'.NormalizerAwareInterface::class.'" instead.') - ->set('serializer.denormalizer.array', ArrayDenormalizer::class) ->tag('serializer.normalizer', ['priority' => -990]) diff --git a/Resources/config/translation.php b/Resources/config/translation.php index dcfa2bc15..a450e6894 100644 --- a/Resources/config/translation.php +++ b/Resources/config/translation.php @@ -27,7 +27,6 @@ use Symfony\Component\Translation\Extractor\ChainExtractor; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\Extractor\PhpAstExtractor; -use Symfony\Component\Translation\Extractor\PhpExtractor; use Symfony\Component\Translation\Extractor\Visitor\ConstraintVisitor; use Symfony\Component\Translation\Extractor\Visitor\TranslatableMessageVisitor; use Symfony\Component\Translation\Extractor\Visitor\TransMethodVisitor; @@ -152,10 +151,6 @@ ->set('translation.dumper.res', IcuResFileDumper::class) ->tag('translation.dumper', ['alias' => 'res']) - ->set('translation.extractor.php', PhpExtractor::class) - ->deprecate('symfony/framework-bundle', '6.2', 'The "%service_id%" service is deprecated, use "translation.extractor.php_ast" instead.') - ->tag('translation.extractor', ['alias' => 'php']) - ->set('translation.extractor.php_ast', PhpAstExtractor::class) ->args([tagged_iterator('translation.extractor.visitor')]) ->tag('translation.extractor', ['alias' => 'php']) diff --git a/Resources/config/workflow.php b/Resources/config/workflow.php index 85d786537..2c47fa960 100644 --- a/Resources/config/workflow.php +++ b/Resources/config/workflow.php @@ -40,10 +40,6 @@ ->set('workflow.marking_store.method', MethodMarkingStore::class) ->abstract() ->set('.workflow.registry', Registry::class) - ->alias(Registry::class, '.workflow.registry') - ->deprecate('symfony/workflow', '6.2', 'The "%alias_id%" alias is deprecated, inject the workflow directly.') - ->alias('workflow.registry', '.workflow.registry') - ->deprecate('symfony/workflow', '6.2', 'The "%alias_id%" alias is deprecated, inject the workflow directly.') ->set('workflow.security.expression_language', ExpressionLanguage::class) ; }; diff --git a/Tests/Controller/AbstractControllerTest.php b/Tests/Controller/AbstractControllerTest.php index efa9c7bec..14e5abd01 100644 --- a/Tests/Controller/AbstractControllerTest.php +++ b/Tests/Controller/AbstractControllerTest.php @@ -471,58 +471,6 @@ public function testRenderWithFormSubmittedAndInvalid() $this->assertSame('bar', $response->getContent()); } - /** - * @group legacy - */ - public function testRenderForm() - { - $formView = new FormView(); - - $form = $this->getMockBuilder(FormInterface::class)->getMock(); - $form->expects($this->once())->method('createView')->willReturn($formView); - - $twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(); - $twig->expects($this->once())->method('render')->with('foo', ['bar' => $formView])->willReturn('bar'); - - $container = new Container(); - $container->set('twig', $twig); - - $controller = $this->createController(); - $controller->setContainer($container); - - $response = $controller->renderForm('foo', ['bar' => $form]); - - $this->assertTrue($response->isSuccessful()); - $this->assertSame('bar', $response->getContent()); - } - - /** - * @group legacy - */ - public function testRenderFormSubmittedAndInvalid() - { - $formView = new FormView(); - - $form = $this->getMockBuilder(FormInterface::class)->getMock(); - $form->expects($this->once())->method('createView')->willReturn($formView); - $form->expects($this->once())->method('isSubmitted')->willReturn(true); - $form->expects($this->once())->method('isValid')->willReturn(false); - - $twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(); - $twig->expects($this->once())->method('render')->with('foo', ['bar' => $formView])->willReturn('bar'); - - $container = new Container(); - $container->set('twig', $twig); - - $controller = $this->createController(); - $controller->setContainer($container); - - $response = $controller->renderForm('foo', ['bar' => $form]); - - $this->assertSame(422, $response->getStatusCode()); - $this->assertSame('bar', $response->getContent()); - } - public function testStreamTwig() { $twig = $this->createMock(Environment::class); diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index e3ecd982d..2e291157a 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -676,7 +676,6 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], 'default_bus' => null, 'buses' => ['messenger.bus.default' => ['default_middleware' => ['enabled' => true, 'allow_no_handlers' => false, 'allow_no_senders' => true], 'middleware' => []]], - 'reset_on_message' => true, 'stop_worker_on_signals' => [], ], 'disallow_search_engine_index' => true, diff --git a/Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php b/Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php deleted file mode 100644 index 3cb006c46..000000000 --- a/Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php +++ /dev/null @@ -1,20 +0,0 @@ -loadFromExtension('framework', [ - 'http_method_override' => false, - 'messenger' => [ - 'reset_on_message' => false, - 'routing' => [ - FooMessage::class => ['sender.bar', 'sender.biz'], - BarMessage::class => 'sender.foo', - ], - 'transports' => [ - 'sender.biz' => 'null://', - 'sender.bar' => 'null://', - 'sender.foo' => 'null://', - ], - ], -]); diff --git a/Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php b/Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php deleted file mode 100644 index ee689ae09..000000000 --- a/Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php +++ /dev/null @@ -1,20 +0,0 @@ -loadFromExtension('framework', [ - 'http_method_override' => false, - 'messenger' => [ - 'reset_on_message' => true, - 'routing' => [ - FooMessage::class => ['sender.bar', 'sender.biz'], - BarMessage::class => 'sender.foo', - ], - 'transports' => [ - 'sender.biz' => 'null://', - 'sender.bar' => 'null://', - 'sender.foo' => 'null://', - ], - ], -]); diff --git a/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml b/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml deleted file mode 100644 index 2e6048fa7..000000000 --- a/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml b/Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml deleted file mode 100644 index c0bc33bcd..000000000 --- a/Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml b/Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml deleted file mode 100644 index 4c208aad2..000000000 --- a/Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 97831b04e..968195153 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -14,7 +14,6 @@ use Doctrine\Common\Annotations\Annotation; use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; @@ -93,8 +92,6 @@ abstract class FrameworkExtensionTestCase extends TestCase { - use ExpectDeprecationTrait; - private static $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); @@ -507,7 +504,7 @@ public function testWorkflowServicesCanBeEnabled() { $container = $this->createContainerFromFile('workflows_enabled'); - $this->assertTrue($container->has(Workflow\Registry::class)); + $this->assertTrue($container->hasDefinition('.workflow.registry')); $this->assertTrue($container->hasDefinition('console.command.workflow_dump')); } @@ -791,26 +788,6 @@ public function testMessengerServicesRemovedWhenDisabled() $this->assertFalse($container->hasDefinition('cache.messenger.restart_workers_signal')); } - /** - * @group legacy - */ - public function testMessengerWithExplictResetOnMessageLegacy() - { - $this->expectDeprecation('Since symfony/framework-bundle 6.1: Option "reset_on_message" at "framework.messenger" is deprecated. It does nothing and will be removed in version 7.0.'); - - $container = $this->createContainerFromFile('messenger_with_explict_reset_on_message_legacy'); - - $this->assertTrue($container->hasDefinition('console.command.messenger_consume_messages')); - $this->assertTrue($container->hasAlias('messenger.default_bus')); - $this->assertTrue($container->getAlias('messenger.default_bus')->isPublic()); - $this->assertTrue($container->hasDefinition('messenger.transport.amqp.factory')); - $this->assertTrue($container->hasDefinition('messenger.transport.redis.factory')); - $this->assertTrue($container->hasDefinition('messenger.transport_factory')); - $this->assertSame(TransportFactory::class, $container->getDefinition('messenger.transport_factory')->getClass()); - $this->assertTrue($container->hasDefinition('messenger.listener.reset_services')); - $this->assertSame('messenger.listener.reset_services', (string) $container->getDefinition('console.command.messenger_consume_messages')->getArgument(5)); - } - public function testMessenger() { $container = $this->createContainerFromFile('messenger', [], true, false); @@ -1117,17 +1094,6 @@ public function testMessengerInvalidWildcardRouting() $this->createContainerFromFile('messenger_routing_invalid_transport'); } - /** - * @group legacy - */ - public function testMessengerWithDisabledResetOnMessage() - { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('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.'); - - $this->createContainerFromFile('messenger_with_disabled_reset_on_message'); - } - public function testTranslator() { $container = $this->createContainerFromFile('full'); diff --git a/Tests/DependencyInjection/XmlFrameworkExtensionTest.php b/Tests/DependencyInjection/XmlFrameworkExtensionTest.php index 36d3f5e37..40b3588d7 100644 --- a/Tests/DependencyInjection/XmlFrameworkExtensionTest.php +++ b/Tests/DependencyInjection/XmlFrameworkExtensionTest.php @@ -33,40 +33,6 @@ public function testMessengerMiddlewareFactoryErroneousFormat() $this->markTestSkipped('XML configuration will not allow erroneous format.'); } - public function testLegacyExceptionsConfig() - { - $container = $this->createContainerFromFile('exceptions_legacy'); - - $configuration = $container->getDefinition('exception_listener')->getArgument(3); - - $this->assertSame([ - \Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class, - \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class, - \Symfony\Component\HttpKernel\Exception\ConflictHttpException::class, - \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class, - ], array_keys($configuration)); - - $this->assertEqualsCanonicalizing([ - 'log_level' => 'info', - 'status_code' => 422, - ], $configuration[\Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class]); - - $this->assertEqualsCanonicalizing([ - 'log_level' => 'info', - 'status_code' => null, - ], $configuration[\Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class]); - - $this->assertEqualsCanonicalizing([ - 'log_level' => 'info', - 'status_code' => null, - ], $configuration[\Symfony\Component\HttpKernel\Exception\ConflictHttpException::class]); - - $this->assertEqualsCanonicalizing([ - 'log_level' => null, - 'status_code' => 500, - ], $configuration[\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class]); - } - public function testRateLimiter() { $container = $this->createContainerFromFile('rate_limiter'); diff --git a/composer.json b/composer.json index 722a4c5f1..069dcc7b4 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,6 @@ "symfony/cache": "^6.4|^7.0", "symfony/config": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", "symfony/event-dispatcher": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", From 230c79ae9f1f5837e2fac0a9fb6cb0c8ad075f33 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sun, 2 Jul 2023 23:52:21 +0200 Subject: [PATCH 008/180] [Components] Convert to native return types --- Command/BuildDebugContainerTrait.php | 2 +- Test/KernelTestCase.php | 1 - Tests/Controller/ControllerResolverTest.php | 1 - Tests/Functional/app/AppKernel.php | 2 +- Tests/Kernel/ConcreteMicroKernel.php | 2 +- Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php | 2 +- 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Command/BuildDebugContainerTrait.php b/Command/BuildDebugContainerTrait.php index 83268ae71..2f625e9e3 100644 --- a/Command/BuildDebugContainerTrait.php +++ b/Command/BuildDebugContainerTrait.php @@ -55,7 +55,7 @@ protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilde $this->prepareContainer($containerBuilder); return $containerBuilder; - }, $kernel, \get_class($kernel)); + }, $kernel, $kernel::class); $container = $buildContainer(); (new XmlFileLoader($container, new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); $locatorPass = new ServiceLocatorTagPass(); diff --git a/Test/KernelTestCase.php b/Test/KernelTestCase.php index 639214a43..e5ef9112c 100644 --- a/Test/KernelTestCase.php +++ b/Test/KernelTestCase.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Contracts\Service\ResetInterface; diff --git a/Tests/Controller/ControllerResolverTest.php b/Tests/Controller/ControllerResolverTest.php index 77e5ba14b..0c51924a4 100644 --- a/Tests/Controller/ControllerResolverTest.php +++ b/Tests/Controller/ControllerResolverTest.php @@ -15,7 +15,6 @@ use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; -use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ContainerAwareController; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; diff --git a/Tests/Functional/app/AppKernel.php b/Tests/Functional/app/AppKernel.php index 3f99eff48..80888c4a7 100644 --- a/Tests/Functional/app/AppKernel.php +++ b/Tests/Functional/app/AppKernel.php @@ -89,7 +89,7 @@ public function __sleep(): array return ['varDir', 'testCase', 'rootConfig', 'environment', 'debug']; } - public function __wakeup() + public function __wakeup(): void { foreach ($this as $k => $v) { if (\is_object($v)) { diff --git a/Tests/Kernel/ConcreteMicroKernel.php b/Tests/Kernel/ConcreteMicroKernel.php index def880b23..a51078adb 100644 --- a/Tests/Kernel/ConcreteMicroKernel.php +++ b/Tests/Kernel/ConcreteMicroKernel.php @@ -68,7 +68,7 @@ public function __sleep(): array throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup() + public function __wakeup(): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } diff --git a/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php b/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php index bf529a580..b15729362 100644 --- a/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php +++ b/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php @@ -69,7 +69,7 @@ public function __sleep(): array throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup() + public function __wakeup(): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } From feae13a7313320d89dc9d1d2736548501a797cca Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 9 Jul 2023 09:55:52 +0200 Subject: [PATCH 009/180] [Mailer] Remove the Sendinblue bridge --- DependencyInjection/FrameworkExtension.php | 1 - Resources/config/mailer_transports.php | 5 ----- 2 files changed, 6 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index cd70004a6..dea020b8f 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2591,7 +2591,6 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', - MailerBridge\Sendinblue\Transport\SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', MailerBridge\Amazon\Transport\SesTransportFactory::class => 'mailer.transport_factory.amazon', ]; diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index 6e2c816f7..fb9d4567e 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -22,7 +22,6 @@ use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; -use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\NativeTransportFactory; use Symfony\Component\Mailer\Transport\NullTransportFactory; @@ -92,10 +91,6 @@ ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.sendinblue', SendinblueTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class) ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory', ['priority' => -100]) From 34ea139335191a46bf2948074932df69fe8c4ba5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 9 Jul 2023 09:58:43 +0200 Subject: [PATCH 010/180] [Notifier] Remove the Sendinblue bridge --- DependencyInjection/FrameworkExtension.php | 1 - Resources/config/notifier_transports.php | 4 ---- 2 files changed, 5 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index cd70004a6..d5970e407 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2759,7 +2759,6 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ NotifierBridge\RocketChat\RocketChatTransportFactory::class => 'notifier.transport_factory.rocket-chat', NotifierBridge\Sendberry\SendberryTransportFactory::class => 'notifier.transport_factory.sendberry', NotifierBridge\SimpleTextin\SimpleTextinTransportFactory::class => 'notifier.transport_factory.simple-textin', - NotifierBridge\Sendinblue\SendinblueTransportFactory::class => 'notifier.transport_factory.sendinblue', NotifierBridge\Sinch\SinchTransportFactory::class => 'notifier.transport_factory.sinch', NotifierBridge\Slack\SlackTransportFactory::class => 'notifier.transport_factory.slack', NotifierBridge\Sms77\Sms77TransportFactory::class => 'notifier.transport_factory.sms77', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 445fe2a47..b1e5e9699 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -126,10 +126,6 @@ ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') - ->set('notifier.transport_factory.sendinblue', Bridge\Sendinblue\SendinblueTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - ->set('notifier.transport_factory.iqsms', Bridge\Iqsms\IqsmsTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') From 85500259147c01b4384d1c5624a51455d6b43e35 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 15 Jul 2023 16:02:21 +0200 Subject: [PATCH 011/180] [FrameworkBundle] Remove doctrine/annotations integration --- CHANGELOG.md | 1 + CacheWarmer/AnnotationsCacheWarmer.php | 114 ----------- .../Compiler/UnusedTagsPass.php | 3 +- DependencyInjection/Configuration.php | 19 +- DependencyInjection/FrameworkExtension.php | 61 +----- Resources/config/annotations.php | 71 ------- .../AnnotationsCacheWarmerTest.php | 191 ------------------ .../DependencyInjection/ConfigurationTest.php | 5 +- .../Fixtures/php/legacy_annotations.php | 10 - .../php/validation_legacy_annotations.php | 15 -- .../Fixtures/xml/legacy_annotations.xml | 16 -- .../xml/validation_legacy_annotations.xml | 17 -- .../Fixtures/yml/legacy_annotations.yml | 7 - .../yml/validation_legacy_annotations.yml | 13 -- .../FrameworkExtensionTestCase.php | 58 +----- Tests/Functional/AutowiringTypesTest.php | 31 --- .../AutowiringTypes/AutowiredServices.php | 19 +- .../AutowiringTypes/no_annotations_cache.yml | 8 - .../app/AutowiringTypes/with_annotations.yml | 6 - composer.json | 2 - 20 files changed, 24 insertions(+), 643 deletions(-) delete mode 100644 CacheWarmer/AnnotationsCacheWarmer.php delete mode 100644 Resources/config/annotations.php delete mode 100644 Tests/CacheWarmer/AnnotationsCacheWarmerTest.php delete mode 100644 Tests/DependencyInjection/Fixtures/php/legacy_annotations.php delete mode 100644 Tests/DependencyInjection/Fixtures/php/validation_legacy_annotations.php delete mode 100644 Tests/DependencyInjection/Fixtures/xml/legacy_annotations.xml delete mode 100644 Tests/DependencyInjection/Fixtures/xml/validation_legacy_annotations.xml delete mode 100644 Tests/DependencyInjection/Fixtures/yml/legacy_annotations.yml delete mode 100644 Tests/DependencyInjection/Fixtures/yml/validation_legacy_annotations.yml delete mode 100644 Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml delete mode 100644 Tests/Functional/app/AutowiringTypes/with_annotations.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index fb6e47029..bf516bbe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ CHANGELOG `Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead * Remove the `Http\Client\HttpClient` service, use `Psr\Http\Client\ClientInterface` instead + * Remove the integration of Doctrine annotations, use native attributes instead 6.4 --- diff --git a/CacheWarmer/AnnotationsCacheWarmer.php b/CacheWarmer/AnnotationsCacheWarmer.php deleted file mode 100644 index 279dc4ec9..000000000 --- a/CacheWarmer/AnnotationsCacheWarmer.php +++ /dev/null @@ -1,114 +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); - } - - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): 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, 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/DependencyInjection/Compiler/UnusedTagsPass.php b/DependencyInjection/Compiler/UnusedTagsPass.php index ae5daac8e..c21b7369d 100644 --- a/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/DependencyInjection/Compiler/UnusedTagsPass.php @@ -23,9 +23,9 @@ class UnusedTagsPass implements CompilerPassInterface { private const KNOWN_TAGS = [ 'annotations.cached_reader', - 'assets.package', 'asset_mapper.compiler', 'asset_mapper.importmap.resolver', + 'assets.package', 'auto_alias', 'cache.pool', 'cache.pool.clearer', @@ -33,7 +33,6 @@ class UnusedTagsPass implements CompilerPassInterface 'chatter.transport_factory', 'config_cache.resource_checker', 'console.command', - 'container.do_not_inline', 'container.env_var_loader', 'container.env_var_processor', 'container.excluded', diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 8ca6a54c0..29048942b 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; -use Doctrine\Common\Annotations\Annotation; use Doctrine\DBAL\Connection; use Psr\Log\LogLevel; use Symfony\Bundle\FullStack; @@ -155,7 +154,7 @@ public function getConfigTreeBuilder(): TreeBuilder $this->addAssetMapperSection($rootNode, $enableIfStandalone); $this->addTranslatorSection($rootNode, $enableIfStandalone); $this->addValidationSection($rootNode, $enableIfStandalone); - $this->addAnnotationsSection($rootNode, $willBeAvailable); + $this->addAnnotationsSection($rootNode); $this->addSerializerSection($rootNode, $enableIfStandalone); $this->addPropertyAccessSection($rootNode, $willBeAvailable); $this->addPropertyInfoSection($rootNode, $enableIfStandalone); @@ -1057,21 +1056,15 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ; } - private function addAnnotationsSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void + private function addAnnotationsSection(ArrayNodeDefinition $rootNode): void { $rootNode ->children() ->arrayNode('annotations') - ->info('annotation configuration') - ->{$willBeAvailable('doctrine/annotations', Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->enumNode('cache') - ->values(['none', 'php_array', 'file']) - ->defaultValue('php_array') - ->end() - ->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end() - ->booleanNode('debug')->defaultValue($this->debug)->end() - ->end() + ->canBeEnabled() + ->validate() + ->ifTrue(static fn (array $v) => $v['enabled']) + ->thenInvalid('Enabling the doctrine/annotations integration is not supported anymore.') ->end() ->end() ; diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index e266ab1f0..d4b16662a 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; use Composer\InstalledVersions; -use Doctrine\Common\Annotations\Reader; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use phpDocumentor\Reflection\DocBlockFactoryInterface; @@ -54,7 +53,6 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -255,7 +253,6 @@ public function load(array $configs, ContainerBuilder $container): void $config = $this->processConfiguration($configuration, $configs); // warmup config enabled - $this->readConfigEnabled('annotations', $container, $config['annotations']); $this->readConfigEnabled('translator', $container, $config['translator']); $this->readConfigEnabled('property_access', $container, $config['property_access']); $this->readConfigEnabled('profiler', $container, $config['profiler']); @@ -363,7 +360,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerWorkflowConfiguration($config['workflows'], $container, $loader); $this->registerDebugConfiguration($config['php_errors'], $container, $loader); $this->registerRouterConfiguration($config['router'], $container, $loader, $config['enabled_locales']); - $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader); $this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader); $this->registerSecretsConfiguration($config['secrets'], $container, $loader); @@ -1600,10 +1596,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder $definition->replaceArgument(0, $config['email_validation_mode']); if (\array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { - $validatorBuilder->addMethodCall('enableAnnotationMapping', [true]); - if ($this->isInitializedConfigEnabled('annotations')) { - $validatorBuilder->addMethodCall('setDoctrineAnnotationReader', [new Reference('annotation_reader')]); - } + $validatorBuilder->addMethodCall('enableAnnotationMapping'); } if (\array_key_exists('static_method', $config) && $config['static_method']) { @@ -1698,58 +1691,6 @@ private function registerMappingFilesFromConfig(ContainerBuilder $container, arr } } - private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader): void - { - if (!$this->isInitializedConfigEnabled('annotations')) { - return; - } - - if (!class_exists(\Doctrine\Common\Annotations\Annotation::class)) { - throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed. Try running "composer require doctrine/annotations".'); - } - - trigger_deprecation('symfony/framework-bundle', '6.4', 'Enabling the integration of Doctrine annotations is deprecated. Set the "framework.annotations.enabled" config option to false.'); - - $loader->load('annotations.php'); - - if ('none' === $config['cache']) { - $container->removeDefinition('annotations.cached_reader'); - - return; - } - - if ('php_array' === $config['cache']) { - $cacheService = 'annotations.cache_adapter'; - - // Enable warmer only if PHP array is used for cache - $definition = $container->findDefinition('annotations.cache_warmer'); - $definition->addTag('kernel.cache_warmer'); - } else { - $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)) { - throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir)); - } - - $container - ->getDefinition('annotations.filesystem_cache_adapter') - ->replaceArgument(2, $cacheDir) - ; - } - - $container - ->getDefinition('annotations.cached_reader') - ->replaceArgument(2, $config['debug']) - // reference the cache provider without using it until AddAnnotationsCachedReaderPass runs - ->addArgument(new ServiceClosureArgument(new Reference($cacheService))) - ; - - $container->setAlias('annotation_reader', 'annotations.cached_reader'); - $container->setAlias(Reader::class, new Alias('annotations.cached_reader', false)); - $container->removeDefinition('annotations.psr_cached_reader'); - } - private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void { if (!$this->readConfigEnabled('property_access', $container, $config)) { diff --git a/Resources/config/annotations.php b/Resources/config/annotations.php deleted file mode 100644 index ddf65175b..000000000 --- a/Resources/config/annotations.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\PsrCachedReader; -use Doctrine\Common\Annotations\Reader; -use Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('annotations.reader', AnnotationReader::class) - ->call('addGlobalIgnoredName', ['required']) - ->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.') - - ->set('annotations.cached_reader', PsrCachedReader::class) - ->args([ - service('annotations.reader'), - inline_service(ArrayAdapter::class), - abstract_arg('Debug-Flag'), - ]) - ->tag('annotations.cached_reader') - ->tag('container.do_not_inline') - ->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.') - - ->set('annotations.filesystem_cache_adapter', FilesystemAdapter::class) - ->args([ - '', - 0, - abstract_arg('Cache-Directory'), - ]) - ->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.') - - ->set('annotations.cache_warmer', AnnotationsCacheWarmer::class) - ->args([ - service('annotations.reader'), - param('kernel.cache_dir').'/annotations.php', - '#^Symfony\\\\(?:Component\\\\HttpKernel\\\\|Bundle\\\\FrameworkBundle\\\\Controller\\\\(?!.*Controller$))#', - param('kernel.debug'), - false, - ]) - ->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.') - - ->set('annotations.cache_adapter', PhpArrayAdapter::class) - ->factory([PhpArrayAdapter::class, 'create']) - ->args([ - param('kernel.cache_dir').'/annotations.php', - service('cache.annotations'), - ]) - ->tag('container.hot_path') - ->deprecate('symfony/framework-bundle', '6.4', 'The "%service_id%" service is deprecated without replacement.') - - ->alias('annotation_reader', 'annotations.reader') - ->deprecate('symfony/framework-bundle', '6.4', 'The "%alias_id%" service alias is deprecated without replacement.') - - ->alias(Reader::class, 'annotation_reader') - ->deprecate('symfony/framework-bundle', '6.4', 'The "%alias_id%" service alias is deprecated without replacement.') - ; -}; diff --git a/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php b/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php deleted file mode 100644 index 6ff003b47..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(); - $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 = 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(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; - } -} diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 2e291157a..bca02cbf2 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -557,10 +557,7 @@ protected static function getBundleDefaultConfig() ], ], 'annotations' => [ - 'cache' => 'php_array', - 'file_cache_dir' => '%kernel.cache_dir%/annotations', - 'debug' => true, - 'enabled' => true, + 'enabled' => false, ], 'serializer' => [ 'default_context' => [], diff --git a/Tests/DependencyInjection/Fixtures/php/legacy_annotations.php b/Tests/DependencyInjection/Fixtures/php/legacy_annotations.php deleted file mode 100644 index a939b34f1..000000000 --- a/Tests/DependencyInjection/Fixtures/php/legacy_annotations.php +++ /dev/null @@ -1,10 +0,0 @@ -loadFromExtension('framework', [ - 'annotations' => [ - 'cache' => 'file', - 'debug' => true, - 'file_cache_dir' => '%kernel.cache_dir%/annotations', - ], - 'http_method_override' => false, -]); diff --git a/Tests/DependencyInjection/Fixtures/php/validation_legacy_annotations.php b/Tests/DependencyInjection/Fixtures/php/validation_legacy_annotations.php deleted file mode 100644 index 48b281e65..000000000 --- a/Tests/DependencyInjection/Fixtures/php/validation_legacy_annotations.php +++ /dev/null @@ -1,15 +0,0 @@ -loadFromExtension('framework', [ - 'annotations' => [ - 'enabled' => true, - ], - 'http_method_override' => false, - 'secret' => 's3cr3t', - 'validation' => [ - 'enabled' => true, - 'enable_annotations' => true, - ], -]); - -$container->setAlias('validator.alias', 'validator')->setPublic(true); diff --git a/Tests/DependencyInjection/Fixtures/xml/legacy_annotations.xml b/Tests/DependencyInjection/Fixtures/xml/legacy_annotations.xml deleted file mode 100644 index 57229dad6..000000000 --- a/Tests/DependencyInjection/Fixtures/xml/legacy_annotations.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/Tests/DependencyInjection/Fixtures/xml/validation_legacy_annotations.xml b/Tests/DependencyInjection/Fixtures/xml/validation_legacy_annotations.xml deleted file mode 100644 index 150473a56..000000000 --- a/Tests/DependencyInjection/Fixtures/xml/validation_legacy_annotations.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/Tests/DependencyInjection/Fixtures/yml/legacy_annotations.yml b/Tests/DependencyInjection/Fixtures/yml/legacy_annotations.yml deleted file mode 100644 index 0d34e986c..000000000 --- a/Tests/DependencyInjection/Fixtures/yml/legacy_annotations.yml +++ /dev/null @@ -1,7 +0,0 @@ -framework: - annotations: - enabled: true - cache: file - debug: true - file_cache_dir: '%kernel.cache_dir%/annotations' - http_method_override: true diff --git a/Tests/DependencyInjection/Fixtures/yml/validation_legacy_annotations.yml b/Tests/DependencyInjection/Fixtures/yml/validation_legacy_annotations.yml deleted file mode 100644 index afee3fe15..000000000 --- a/Tests/DependencyInjection/Fixtures/yml/validation_legacy_annotations.yml +++ /dev/null @@ -1,13 +0,0 @@ -framework: - annotations: - enabled: true - http_method_override: false - secret: s3cr3t - validation: - enabled: true - enable_annotations: true - -services: - validator.alias: - alias: validator - public: true diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index da4468c2e..12ae8ccef 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -35,7 +35,6 @@ use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -94,7 +93,7 @@ abstract class FrameworkExtensionTestCase extends TestCase { use ExpectDeprecationTrait; - private static $containerCache = []; + private static array $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); @@ -1223,19 +1222,16 @@ public function testValidationService() $this->assertInstanceOf(ValidatorInterface::class, $container->get('validator.alias')); } - /** - * @group legacy - */ public function testAnnotations() { - $this->expectDeprecation('Since symfony/framework-bundle 6.4: Enabling the integration of Doctrine annotations is deprecated. Set the "framework.annotations.enabled" config option to false.'); - - $container = $this->createContainerFromFile('legacy_annotations', [], true, false); - $container->addCompilerPass(new TestAnnotationsPass()); - $container->compile(); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('Invalid configuration for path "framework.annotations": Enabling the doctrine/annotations integration is not supported anymore.'); - $this->assertEquals($container->getParameter('kernel.cache_dir').'/annotations', $container->getDefinition('annotations.filesystem_cache_adapter')->getArgument(2)); - $this->assertSame('annotations.filesystem_cache_adapter', (string) $container->getDefinition('annotation_reader')->getArgument(1)); + $this->createContainerFromClosure(function (ContainerBuilder $container) { + $container->loadFromExtension('framework', [ + 'annotations' => true, + ]); + }); } public function testFileLinkFormat() @@ -1264,28 +1260,6 @@ public function testValidationAnnotations() // no cache this time } - /** - * @group legacy - */ - public function testValidationLegacyAnnotations() - { - $this->expectDeprecation('Since symfony/framework-bundle 6.4: Enabling the integration of Doctrine annotations is deprecated. Set the "framework.annotations.enabled" config option to false.'); - - $container = $this->createContainerFromFile('validation_legacy_annotations'); - - $calls = $container->getDefinition('validator.builder')->getMethodCalls(); - - $this->assertCount(8, $calls); - $this->assertSame('enableAnnotationMapping', $calls[4][0]); - $this->assertSame('setDoctrineAnnotationReader', $calls[5][0]); - $this->assertEquals([new Reference('annotation_reader')], $calls[5][1]); - $this->assertSame('addMethodMapping', $calls[6][0]); - $this->assertSame(['loadValidatorMetadata'], $calls[6][1]); - $this->assertSame('setMappingCache', $calls[7][0]); - $this->assertEquals([new Reference('validator.mapping.cache.adapter')], $calls[7][1]); - // no cache this time - } - public function testValidationPaths() { require_once __DIR__.'/Fixtures/TestBundle/TestBundle.php'; @@ -2317,7 +2291,7 @@ protected function createContainer(array $data = []) ], $data))); } - protected function createContainerFromFile(string $file, array $data = [], bool $resetCompilerPasses = true, bool $compile = true, FrameworkExtension $extension = null) + protected function createContainerFromFile(string $file, array $data = [], bool $resetCompilerPasses = true, bool $compile = true, FrameworkExtension $extension = null): ContainerBuilder { $cacheKey = md5(static::class.$file.serialize($data)); if ($compile && isset(self::$containerCache[$cacheKey])) { @@ -2344,7 +2318,7 @@ protected function createContainerFromFile(string $file, array $data = [], bool return self::$containerCache[$cacheKey] = $container; } - protected function createContainerFromClosure($closure, $data = []) + protected function createContainerFromClosure($closure, $data = []): ContainerBuilder { $container = $this->createContainer($data); $container->registerExtension(new FrameworkExtension()); @@ -2416,15 +2390,3 @@ private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $con }; } } - -/** - * Simulates ReplaceAliasByActualDefinitionPass. - */ -class TestAnnotationsPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - $container->setDefinition('annotation_reader', $container->getDefinition('annotations.cached_reader')); - $container->removeDefinition('annotations.cached_reader'); - } -} diff --git a/Tests/Functional/AutowiringTypesTest.php b/Tests/Functional/AutowiringTypesTest.php index 95f99ef2c..28ce69f93 100644 --- a/Tests/Functional/AutowiringTypesTest.php +++ b/Tests/Functional/AutowiringTypesTest.php @@ -11,9 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\PsrCachedReader; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; @@ -21,34 +18,6 @@ class AutowiringTypesTest extends AbstractWebTestCase { - use ExpectDeprecationTrait; - - /** - * @group legacy - */ - public function testAnnotationReaderAutowiring() - { - $this->expectDeprecation('Since symfony/framework-bundle 6.4: Enabling the integration of Doctrine annotations is deprecated. Set the "framework.annotations.enabled" config option to false.'); - - static::bootKernel(['root_config' => 'no_annotations_cache.yml', 'environment' => 'no_annotations_cache']); - - $annotationReader = self::getContainer()->get('test.autowiring_types.autowired_services')->getAnnotationReader(); - $this->assertInstanceOf(AnnotationReader::class, $annotationReader); - } - - /** - * @group legacy - */ - public function testCachedAnnotationReaderAutowiring() - { - $this->expectDeprecation('Since symfony/framework-bundle 6.4: Enabling the integration of Doctrine annotations is deprecated. Set the "framework.annotations.enabled" config option to false.'); - - static::bootKernel(['root_config' => 'with_annotations.yml', 'environment' => 'with_annotations']); - - $annotationReader = self::getContainer()->get('test.autowiring_types.autowired_services')->getAnnotationReader(); - $this->assertInstanceOf(PsrCachedReader::class, $annotationReader); - } - public function testEventDispatcherAutowiring() { static::bootKernel(['debug' => false]); diff --git a/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php b/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php index 4743460e6..c5a5decce 100644 --- a/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php +++ b/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php @@ -11,26 +11,15 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\AutowiringTypes; -use Doctrine\Common\Annotations\Reader; use Psr\Cache\CacheItemPoolInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class AutowiredServices { - private $annotationReader; - private $dispatcher; - private $cachePool; - - public function __construct(Reader $annotationReader = null, EventDispatcherInterface $dispatcher, CacheItemPoolInterface $cachePool) - { - $this->annotationReader = $annotationReader; - $this->dispatcher = $dispatcher; - $this->cachePool = $cachePool; - } - - public function getAnnotationReader() - { - return $this->annotationReader; + public function __construct( + private readonly EventDispatcherInterface $dispatcher, + private readonly CacheItemPoolInterface $cachePool, + ) { } public function getDispatcher() diff --git a/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml b/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml deleted file mode 100644 index fa78d7200..000000000 --- a/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml +++ /dev/null @@ -1,8 +0,0 @@ -imports: - - { resource: config.yml } - -framework: - http_method_override: false - annotations: - enabled: true - cache: none diff --git a/Tests/Functional/app/AutowiringTypes/with_annotations.yml b/Tests/Functional/app/AutowiringTypes/with_annotations.yml deleted file mode 100644 index cb87d7f4e..000000000 --- a/Tests/Functional/app/AutowiringTypes/with_annotations.yml +++ /dev/null @@ -1,6 +0,0 @@ -imports: - - { resource: config.yml } - -framework: - annotations: - enabled: true diff --git a/composer.json b/composer.json index 722a4c5f1..bf371b6e8 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,6 @@ "symfony/routing": "^6.4|^7.0" }, "require-dev": { - "doctrine/annotations": "^1.13.1|^2", "doctrine/persistence": "^1.3|^2|^3", "symfony/asset": "^6.4|^7.0", "symfony/asset-mapper": "^6.4|^7.0", @@ -73,7 +72,6 @@ "twig/twig": "^2.10|^3.0" }, "conflict": { - "doctrine/annotations": "<1.13.1", "doctrine/persistence": "<1.3", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", From d615ca1a435e425bede38ab5fe28c07bd11696ca Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 24 Jul 2023 14:01:38 +0200 Subject: [PATCH 012/180] Fix merge --- DependencyInjection/FrameworkExtension.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index c948a1daf..6b49ac7a7 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -140,7 +140,6 @@ use Symfony\Component\RateLimiter\Storage\CacheStorage; use Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer; use Symfony\Component\RemoteEvent\RemoteEvent; -use Symfony\Component\Routing\Loader\AnnotationClassLoader; use Symfony\Component\Routing\Loader\Psr4DirectoryLoader; use Symfony\Component\Scheduler\Attribute\AsSchedule; use Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory; @@ -1169,13 +1168,6 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co if (!class_exists(Psr4DirectoryLoader::class)) { $container->removeDefinition('routing.loader.psr4'); } - - if ($this->isInitializedConfigEnabled('annotations') && (new \ReflectionClass(AnnotationClassLoader::class))->hasProperty('reader')) { - $container->getDefinition('routing.loader.annotation')->setArguments([ - new Reference('annotation_reader'), - '%kernel.environment%', - ]); - } } private function registerSessionConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void From dbe315a278a2f16058c277202ed9dcc86afcbdb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 24 Jul 2023 17:21:55 +0200 Subject: [PATCH 013/180] [FrameworkBundle][Workflow] Remove dead code --- Command/WorkflowDumpCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Command/WorkflowDumpCommand.php b/Command/WorkflowDumpCommand.php index f69a0e11e..d732305d4 100644 --- a/Command/WorkflowDumpCommand.php +++ b/Command/WorkflowDumpCommand.php @@ -81,10 +81,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; $definition = $workflow->getDefinition(); - if (null === $definition) { - throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName)); - } - switch ($input->getOption('dump-format')) { case 'puml': $transitionType = 'workflow' === $type ? PlantUmlDumper::WORKFLOW_TRANSITION : PlantUmlDumper::STATEMACHINE_TRANSITION; From 4137cb3fcf10cefafade6339cc34fe749d2563a1 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 21 Jul 2023 16:36:29 +0200 Subject: [PATCH 014/180] [Messenger] Remove deprecated `StopWorkerOnSignalsListener` --- DependencyInjection/FrameworkExtension.php | 7 ------- Resources/config/messenger.php | 10 ---------- 2 files changed, 17 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 2d3b0cf10..2c8cd891b 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -108,7 +108,6 @@ use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Messenger\Bridge as MessengerBridge; use Symfony\Component\Messenger\Command\StatsCommand; -use Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener; use Symfony\Component\Messenger\Handler\BatchHandlerInterface; use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; @@ -2035,12 +2034,6 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $container->getDefinition('messenger.transport.beanstalkd.factory')->addTag('messenger.transport_factory'); } - if (!class_exists(StopWorkerOnSignalsListener::class)) { - $container->removeDefinition('messenger.listener.stop_worker_signals_listener'); - } elseif ($config['stop_worker_on_signals']) { - $container->getDefinition('messenger.listener.stop_worker_signals_listener')->replaceArgument(0, $config['stop_worker_on_signals']); - } - if (null === $config['default_bus'] && 1 === \count($config['buses'])) { $config['default_bus'] = key($config['buses']); } diff --git a/Resources/config/messenger.php b/Resources/config/messenger.php index 56b50d78d..556affd07 100644 --- a/Resources/config/messenger.php +++ b/Resources/config/messenger.php @@ -23,7 +23,6 @@ use Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener; use Symfony\Component\Messenger\EventListener\StopWorkerOnCustomStopExceptionListener; use Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener; -use Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener; use Symfony\Component\Messenger\Handler\RedispatchMessageHandler; use Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware; use Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware; @@ -201,15 +200,6 @@ ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'messenger']) - ->set('messenger.listener.stop_worker_signals_listener', StopWorkerOnSignalsListener::class) - ->deprecate('6.4', 'symfony/messenger', 'The "%service_id%" service is deprecated, use the "Symfony\Component\Console\Command\SignalableCommandInterface" instead.') - ->args([ - null, - service('logger')->ignoreOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'messenger']) - ->set('messenger.listener.stop_worker_on_stop_exception_listener', StopWorkerOnCustomStopExceptionListener::class) ->tag('kernel.event_subscriber') From d27d89c588d63a097409abc9c089a9b4d719654d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 21 Jul 2023 15:36:26 +0200 Subject: [PATCH 015/180] Add types to public and protected properties --- Controller/AbstractController.php | 5 +---- HttpCache/HttpCache.php | 4 ++-- Secrets/AbstractVault.php | 2 +- Test/KernelTestCase.php | 11 +++-------- Translation/Translator.php | 7 +++---- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Controller/AbstractController.php b/Controller/AbstractController.php index 3149f1ae8..6cdfb3d8a 100644 --- a/Controller/AbstractController.php +++ b/Controller/AbstractController.php @@ -55,10 +55,7 @@ */ abstract class AbstractController implements ServiceSubscriberInterface { - /** - * @var ContainerInterface - */ - protected $container; + protected ContainerInterface $container; #[Required] public function setContainer(ContainerInterface $container): ?ContainerInterface diff --git a/HttpCache/HttpCache.php b/HttpCache/HttpCache.php index f312a7afe..ab8cae6b7 100644 --- a/HttpCache/HttpCache.php +++ b/HttpCache/HttpCache.php @@ -27,8 +27,8 @@ */ class HttpCache extends BaseHttpCache { - protected $cacheDir; - protected $kernel; + protected ?string $cacheDir = null; + protected KernelInterface $kernel; private ?StoreInterface $store = null; private ?SurrogateInterface $surrogate; diff --git a/Secrets/AbstractVault.php b/Secrets/AbstractVault.php index ac2078f6d..374964a06 100644 --- a/Secrets/AbstractVault.php +++ b/Secrets/AbstractVault.php @@ -16,7 +16,7 @@ */ abstract class AbstractVault { - protected $lastMessage; + protected ?string $lastMessage = null; public function getLastMessage(): ?string { diff --git a/Test/KernelTestCase.php b/Test/KernelTestCase.php index e5ef9112c..d14c4dde8 100644 --- a/Test/KernelTestCase.php +++ b/Test/KernelTestCase.php @@ -27,14 +27,9 @@ abstract class KernelTestCase extends TestCase use MailerAssertionsTrait; use NotificationAssertionsTrait; - protected static $class; - - /** - * @var KernelInterface - */ - protected static $kernel; - - protected static $booted = false; + protected static ?string $class = null; + protected static ?KernelInterface $kernel = null; + protected static bool $booted = false; protected function tearDown(): void { diff --git a/Translation/Translator.php b/Translation/Translator.php index 3cce60ec1..de1f4f925 100644 --- a/Translation/Translator.php +++ b/Translation/Translator.php @@ -24,10 +24,9 @@ */ class Translator extends BaseTranslator implements WarmableInterface { - protected $container; - protected $loaderIds; - - protected $options = [ + protected ContainerInterface $container; + protected array $loaderIds; + protected array $options = [ 'cache_dir' => null, 'debug' => false, 'resource_files' => [], From f36e094719c045a8ad3cfa0ec47b4912a5c796fe Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 5 Aug 2023 16:46:07 +0200 Subject: [PATCH 016/180] [MonologBridge][FrameworkBundle] Remove recently deprecated symbols --- CHANGELOG.md | 2 + .../Compiler/AddDebugLogProcessorPass.php | 12 ----- .../Compiler/EnableLoggerDebugModePass.php | 44 ------------------- 3 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 DependencyInjection/Compiler/EnableLoggerDebugModePass.php diff --git a/CHANGELOG.md b/CHANGELOG.md index a233efb4e..aaf735d49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ CHANGELOG `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead * Remove the `Http\Client\HttpClient` service, use `Psr\Http\Client\ClientInterface` instead * Remove the integration of Doctrine annotations, use native attributes instead + * Remove `EnableLoggerDebugModePass`, use argument `$debug` of HttpKernel's `Logger` instead + * Remove `AddDebugLogProcessorPass::configureLogger()`, use HttpKernel's `DebugLoggerConfigurator` instead 6.4 --- diff --git a/DependencyInjection/Compiler/AddDebugLogProcessorPass.php b/DependencyInjection/Compiler/AddDebugLogProcessorPass.php index 68a1e51b0..1efdcb87f 100644 --- a/DependencyInjection/Compiler/AddDebugLogProcessorPass.php +++ b/DependencyInjection/Compiler/AddDebugLogProcessorPass.php @@ -32,16 +32,4 @@ public function process(ContainerBuilder $container): void $container->getDefinition('monolog.logger_prototype') ->setConfigurator([new Reference('debug.debug_logger_configurator'), 'pushDebugLogger']); } - - /** - * @deprecated since Symfony 6.4, use HttpKernel's DebugLoggerConfigurator instead - */ - public static function configureLogger(mixed $logger): void - { - trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s()" method is deprecated, use HttpKernel\'s DebugLoggerConfigurator instead.', __METHOD__); - - if (\is_object($logger) && method_exists($logger, 'removeDebugLogger') && \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - $logger->removeDebugLogger(); - } - } } diff --git a/DependencyInjection/Compiler/EnableLoggerDebugModePass.php b/DependencyInjection/Compiler/EnableLoggerDebugModePass.php deleted file mode 100644 index c1a5e444f..000000000 --- a/DependencyInjection/Compiler/EnableLoggerDebugModePass.php +++ /dev/null @@ -1,44 +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\DependencyInjection\Compiler; - -trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use argument $debug of HttpKernel\'s Logger instead.', EnableLoggerDebugModePass::class); - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Log\Logger; - -/** - * @deprecated since Symfony 6.4, use argument $debug of HttpKernel's Logger instead - */ -final class EnableLoggerDebugModePass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (!$container->hasDefinition('profiler') || !$container->hasDefinition('logger')) { - return; - } - - $loggerDefinition = $container->getDefinition('logger'); - - if (Logger::class === $loggerDefinition->getClass()) { - $loggerDefinition->setConfigurator([__CLASS__, 'configureLogger']); - } - } - - public static function configureLogger(Logger $logger): void - { - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - $logger->enableDebug(); - } - } -} From c855b63bf32c0f0c98ecead79d552832901ba560 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 18 Aug 2023 16:58:37 +0200 Subject: [PATCH 017/180] [FrameworkBundle] Remove config deprecations --- CHANGELOG.md | 8 ++ DependencyInjection/Configuration.php | 100 +++--------------- DependencyInjection/FrameworkExtension.php | 8 +- .../DependencyInjection/ConfigurationTest.php | 10 +- 4 files changed, 32 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad847a244..03cf42722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ CHANGELOG * Remove the integration of Doctrine annotations, use native attributes instead * Remove `EnableLoggerDebugModePass`, use argument `$debug` of HttpKernel's `Logger` instead * Remove `AddDebugLogProcessorPass::configureLogger()`, use HttpKernel's `DebugLoggerConfigurator` instead + * Make the `framework.handle_all_throwables` config option default to `true` + * Make the `framework.php_errors.log` config option default to `true` + * Make the `framework.session.cookie_secure` config option default to `auto` + * Make the `framework.session.cookie_samesite` config option default to `lax` + * Make the `framework.session.handler_id` default to null if `save_path` is not set and to `session.handler.native_file` otherwise + * Make the `framework.uid.default_uuid_version` config option default to `7` + * Make the `framework.uid.time_based_uuid_version` config option default to `7` + * Make the `framework.validation.email_validation_mode` config option default to `html5` 6.4 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 4782cb70a..72460206b 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -82,15 +82,6 @@ public function getConfigTreeBuilder(): TreeBuilder return $v; }) ->end() - ->validate() - ->always(function ($v) { - if (!isset($v['handle_all_throwables'])) { - trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.handle_all_throwables" config option is deprecated. It will default to "true" in 7.0.'); - } - - return $v; - }) - ->end() ->fixXmlConfig('enabled_locale') ->children() ->scalarNode('secret')->end() @@ -137,7 +128,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarNode('error_controller') ->defaultValue('error_controller') ->end() - ->booleanNode('handle_all_throwables')->info('HttpKernel will handle all kinds of \Throwable')->end() + ->booleanNode('handle_all_throwables')->info('HttpKernel will handle all kinds of \Throwable')->defaultTrue()->end() ->end() ; @@ -649,38 +640,15 @@ private function addRouterSection(ArrayNodeDefinition $rootNode): void private function addSessionSection(ArrayNodeDefinition $rootNode): void { $rootNode - ->validate() - ->always(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.'); - } - - if (!\array_key_exists('cookie_samesite', $v['session'])) { - trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.session.cookie_samesite" config option is deprecated. It will default to "lax" in 7.0.'); - } - - if (!\array_key_exists('handler_id', $v['session']) && !\array_key_exists('handler_id', $v['save_path'])) { - trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting either "framework.session.handler_id" or "save_path" config options is deprecated; "handler_id" will default to null in 7.0 if "save_path" is not set and to "session.handler.native_file" otherwise.'); - } - } - - $v['session'] += [ - 'cookie_samesite' => null, - 'handler_id' => 'session.handler.native_file', - 'save_path' => '%kernel.cache_dir%/sessions', - ]; - - return $v; - }) - ->end() ->children() ->arrayNode('session') ->info('session configuration') ->canBeEnabled() ->children() ->scalarNode('storage_factory_id')->defaultValue('session.storage.factory.native')->end() - ->scalarNode('handler_id')->end() + ->scalarNode('handler_id') + ->info('Defaults to using the native session handler, or to the native *file* session handler if "save_path" is not null.') + ->end() ->scalarNode('name') ->validate() ->ifTrue(function ($v) { @@ -694,14 +662,16 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void ->scalarNode('cookie_lifetime')->end() ->scalarNode('cookie_path')->end() ->scalarNode('cookie_domain')->end() - ->enumNode('cookie_secure')->values([true, false, 'auto'])->end() + ->enumNode('cookie_secure')->values([true, false, 'auto'])->defaultValue('auto')->end() ->booleanNode('cookie_httponly')->defaultTrue()->end() - ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->end() + ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultValue('lax')->end() ->booleanNode('use_cookies')->end() ->scalarNode('gc_divisor')->end() ->scalarNode('gc_probability')->defaultValue(1)->end() ->scalarNode('gc_maxlifetime')->end() - ->scalarNode('save_path')->end() + ->scalarNode('save_path') + ->info('Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null') + ->end() ->integerNode('metadata_update_threshold') ->defaultValue(0) ->info('seconds to wait between 2 session metadata updates') @@ -1013,25 +983,6 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e private function addValidationSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void { $rootNode - ->validate() - ->always(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.'); - } - - if (isset($v['enable_annotations'])) { - 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'])) { - $v['enable_attributes'] = $v['enable_annotations']; - } else { - throw new LogicException('The "enable_annotations" and "enable_attributes" options at path "framework.validation" must not be both set. Only the "enable_attributes" option must be used.'); - } - } - - return $v; - }) - ->end() ->children() ->arrayNode('validation') ->info('validation configuration') @@ -1047,7 +998,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->validate()->castToArray()->end() ->end() ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end() + ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->defaultValue('html5')->end() ->arrayNode('mapping') ->addDefaultsIfNotSet() ->fixXmlConfig('path') @@ -1312,17 +1263,6 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe private function addPhpErrorsSection(ArrayNodeDefinition $rootNode): void { $rootNode - ->validate() - ->always(function (array $v): array { - if (!\array_key_exists('log', $v['php_errors'])) { - trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.php_errors.log" config option is deprecated. It will default to "true" in 7.0.'); - - $v['php_errors']['log'] = $this->debug; - } - - return $v; - }) - ->end() ->children() ->arrayNode('php_errors') ->info('PHP errors handling configuration') @@ -1332,6 +1272,7 @@ private function addPhpErrorsSection(ArrayNodeDefinition $rootNode): void ->info('Use the application logger instead of the PHP logger for logging PHP errors.') ->example('"true" to use the default configuration: log all errors. "false" to disable. An integer bit field of E_* constants, or an array mapping E_* constants to log levels.') ->treatNullLike($this->debug) + ->defaultTrue() ->beforeNormalization() ->ifArray() ->then(function (array $v): array { @@ -2344,23 +2285,6 @@ private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $ private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void { $rootNode - ->validate() - ->always(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.'); - } - - if (!\array_key_exists('time_based_uuid_version', $v['uid'])) { - trigger_deprecation('symfony/framework-bundle', '6.4', 'Not setting the "framework.uid.time_based_uuid_version" config option is deprecated. It will default to "7" in 7.0.'); - } - } - - $v['uid'] += ['default_uuid_version' => 6, 'time_based_uuid_version' => 6]; - - return $v; - }) - ->end() ->children() ->arrayNode('uid') ->info('Uid configuration') @@ -2369,6 +2293,7 @@ private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIf ->children() ->enumNode('default_uuid_version') ->values([7, 6, 4, 1]) + ->defaultValue(7) ->end() ->enumNode('name_based_uuid_version') ->defaultValue(5) @@ -2379,6 +2304,7 @@ private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIf ->end() ->enumNode('time_based_uuid_version') ->values([7, 6, 1]) + ->defaultValue(7) ->end() ->scalarNode('time_based_uuid_node') ->cannotBeEmpty() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 57cf7d4c6..e3101a664 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -181,7 +181,6 @@ use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; use Symfony\Component\Validator\ObjectInitializerInterface; use Symfony\Component\Validator\Validation; -use Symfony\Component\Validator\ValidatorBuilder; use Symfony\Component\Webhook\Controller\WebhookController; use Symfony\Component\WebLink\HttpHeaderSerializer; use Symfony\Component\Workflow; @@ -1232,10 +1231,15 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c $container->setParameter('session.storage.options', $options); // session handler (the internal callback registered with PHP session management) - if (null === $config['handler_id']) { + if (null === ($config['handler_id'] ?? $config['save_path'] ?? null)) { $config['save_path'] = null; $container->setAlias('session.handler', 'session.handler.native'); } else { + $config['handler_id'] ??= 'session.handler.native_file'; + + if (!\array_key_exists('save_path', $config)) { + $config['save_path'] = '%kernel.cache_dir%/sessions'; + } $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs); if ($usedEnvs || preg_match('#^[a-z]++://#', $config['handler_id'])) { diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 2865a406b..c6c4b398a 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -602,6 +602,7 @@ protected static function getBundleDefaultConfig() 'enabled' => true, 'endpoint' => null, ], + 'email_validation_mode' => 'html5', ], 'annotations' => [ 'enabled' => false, @@ -635,11 +636,10 @@ protected static function getBundleDefaultConfig() 'session' => [ 'enabled' => false, 'storage_factory_id' => 'session.storage.factory.native', - 'handler_id' => 'session.handler.native_file', 'cookie_httponly' => true, - 'cookie_samesite' => null, + 'cookie_samesite' => 'lax', + 'cookie_secure' => 'auto', 'gc_probability' => 1, - 'save_path' => '%kernel.cache_dir%/sessions', 'metadata_update_threshold' => 0, ], 'request' => [ @@ -762,9 +762,9 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], 'uid' => [ 'enabled' => !class_exists(FullStack::class) && class_exists(UuidFactory::class), - 'default_uuid_version' => 6, + 'default_uuid_version' => 7, 'name_based_uuid_version' => 5, - 'time_based_uuid_version' => 6, + 'time_based_uuid_version' => 7, ], 'html_sanitizer' => [ 'enabled' => !class_exists(FullStack::class) && class_exists(HtmlSanitizer::class), From 1817356a523d93a1881a5f819525e5a92a23bbd7 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 22 Aug 2023 15:45:13 +0200 Subject: [PATCH 018/180] [FrameworkBundle][Validator] Remove remaining deprecations --- CHANGELOG.md | 2 ++ DependencyInjection/Configuration.php | 16 ---------------- Resources/config/schema/symfony-1.0.xsd | 2 -- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00d71e31e..8117ffe6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ CHANGELOG * Make the `framework.uid.default_uuid_version` config option default to `7` * Make the `framework.uid.time_based_uuid_version` config option default to `7` * Make the `framework.validation.email_validation_mode` config option default to `html5` + * Remove the `framework.validation.enable_annotations` config option, use `framework.validation.enable_attributes` instead + * Remove the `framework.serializer.enable_annotations` config option, use `framework.serializer.enable_attributes` instead 6.4 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 72460206b..a728efc2f 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -989,7 +989,6 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->{$enableIfStandalone('symfony/validator', Validation::class)}() ->children() ->scalarNode('cache')->end() - ->booleanNode('enable_annotations')->end() ->booleanNode('enable_attributes')->{!class_exists(FullStack::class) ? 'defaultTrue' : 'defaultFalse'}()->end() ->arrayNode('static_method') ->defaultValue(['loadValidatorMetadata']) @@ -1090,24 +1089,9 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e $rootNode ->children() ->arrayNode('serializer') - ->validate() - ->always(function ($v) { - if (isset($v['enable_annotations'])) { - 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'])) { - $v['enable_attributes'] = $v['enable_annotations']; - } else { - throw new LogicException('The "enable_annotations" and "enable_attributes" options at path "framework.serializer" must not be both set. Only the "enable_attributes" option must be used.'); - } - } - - return $v; - })->end() ->info('serializer configuration') ->{$enableIfStandalone('symfony/serializer', Serializer::class)}() ->children() - ->booleanNode('enable_annotations')->end() ->booleanNode('enable_attributes')->{!class_exists(FullStack::class) ? 'defaultTrue' : 'defaultFalse'}()->end() ->scalarNode('name_converter')->end() ->scalarNode('circular_reference_handler')->end() diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index 001b36d8e..c3f2f9670 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -266,7 +266,6 @@ - @@ -320,7 +319,6 @@ - From dbca7742f24bf0b0109c17f92eba9a87e880b1bf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 24 Aug 2023 17:26:29 +0200 Subject: [PATCH 019/180] [FrameworkBundle] Remove compat code --- DependencyInjection/FrameworkExtension.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index e3101a664..9c9a8af29 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1851,12 +1851,6 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->removeDefinition('serializer.normalizer.translatable'); } - // compat with Symfony < 6.3 - if (!is_subclass_of(ProblemNormalizer::class, SerializerAwareInterface::class)) { - $container->getDefinition('serializer.normalizer.problem') - ->setArguments(['%kernel.debug%']); - } - $serializerLoaders = []; if (isset($config['enable_attributes']) && $config['enable_attributes']) { if ($container->getParameter('kernel.debug')) { From 50d420b5cba7b4b9de2f1653213dc6456e0d4cba Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 3 Sep 2023 16:53:03 +0200 Subject: [PATCH 020/180] [FrameworkBundle] Remove references to annotation_reader --- .../AddAnnotationsCachedReaderPass.php | 43 ------------------- .../Compiler/UnusedTagsPass.php | 1 - DependencyInjection/FrameworkExtension.php | 8 +--- FrameworkBundle.php | 2 - .../FrameworkExtensionTestCase.php | 4 -- .../AnnotationReaderPass.php | 24 ----------- .../Bundle/TestBundle/TestBundle.php | 1 - 7 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php delete mode 100644 Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php diff --git a/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php deleted file mode 100644 index 2105a54df..000000000 --- a/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php +++ /dev/null @@ -1,43 +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\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @internal - */ -class AddAnnotationsCachedReaderPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - // "annotations.cached_reader" is wired late so that any passes using - // "annotation_reader" at build time don't get any cache - foreach ($container->findTaggedServiceIds('annotations.cached_reader') as $id => $tags) { - $reader = $container->getDefinition($id); - $properties = $reader->getProperties(); - - if (isset($properties['cacheProviderBackup'])) { - $provider = $properties['cacheProviderBackup']->getValues()[0]; - unset($properties['cacheProviderBackup']); - $reader->setProperties($properties); - $reader->replaceArgument(1, $provider); - } elseif (4 <= \count($arguments = $reader->getArguments()) && $arguments[3] instanceof ServiceClosureArgument) { - $arguments[1] = $arguments[3]->getValues()[0]; - unset($arguments[3]); - $reader->setArguments($arguments); - } - } - } -} diff --git a/DependencyInjection/Compiler/UnusedTagsPass.php b/DependencyInjection/Compiler/UnusedTagsPass.php index c21b7369d..b0b20e1a1 100644 --- a/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/DependencyInjection/Compiler/UnusedTagsPass.php @@ -22,7 +22,6 @@ class UnusedTagsPass implements CompilerPassInterface { private const KNOWN_TAGS = [ - 'annotations.cached_reader', 'asset_mapper.compiler', 'asset_mapper.importmap.resolver', 'assets.package', diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index e7d2f7758..1995e1ba7 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -161,10 +161,8 @@ use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\Normalizer\ProblemNormalizer; use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer; use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\String\LazyString; use Symfony\Component\String\Slugger\SluggerInterface; @@ -715,7 +713,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('routing.route_loader'); $container->setParameter('container.behavior_describing_tags', [ - 'annotations.cached_reader', 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', @@ -1857,10 +1854,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); } - $annotationLoader = new Definition( - AnnotationLoader::class, - [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)] - ); + $annotationLoader = new Definition(AnnotationLoader::class); $serializerLoaders[] = $annotationLoader; } diff --git a/FrameworkBundle.php b/FrameworkBundle.php index cf195c522..25c1aca2a 100644 --- a/FrameworkBundle.php +++ b/FrameworkBundle.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AssetsContextPass; @@ -142,7 +141,6 @@ public function build(ContainerBuilder $container): void // but as late as possible to get resolved parameters $container->addCompilerPass($registerListenersPass, PassConfig::TYPE_BEFORE_REMOVING); $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class); - $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255); $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING); // must be registered as late as possible to get access to all Twig paths registered in diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 0e08e29f6..665112998 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -14,7 +14,6 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; @@ -81,7 +80,6 @@ use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Validator\ValidatorInterface; -use Symfony\Component\Validator\ValidatorBuilder; use Symfony\Component\Webhook\Client\RequestParser; use Symfony\Component\Webhook\Controller\WebhookController; use Symfony\Component\Workflow; @@ -2048,7 +2046,6 @@ public function testRegisterParameterCollectingBehaviorDescribingTags() $this->assertTrue($container->hasParameter('container.behavior_describing_tags')); $this->assertEquals([ - 'annotations.cached_reader', 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', @@ -2321,7 +2318,6 @@ protected function createContainerFromFile(string $file, array $data = [], bool } $container->getCompilerPassConfig()->setBeforeOptimizationPasses([new LoggerPass()]); $container->getCompilerPassConfig()->setBeforeRemovingPasses([new AddConstraintValidatorsPass(), new TranslatorPass()]); - $container->getCompilerPassConfig()->setAfterRemovingPasses([new AddAnnotationsCachedReaderPass()]); if (!$compile) { return $container; diff --git a/Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php b/Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php deleted file mode 100644 index 9e61c5ae7..000000000 --- a/Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php +++ /dev/null @@ -1,24 +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\Functional\Bundle\TestBundle\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -class AnnotationReaderPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - // simulate using "annotation_reader" in a compiler pass - $container->get('test.annotation_reader'); - } -} diff --git a/Tests/Functional/Bundle/TestBundle/TestBundle.php b/Tests/Functional/Bundle/TestBundle/TestBundle.php index 7dbbb096b..d0c6588b0 100644 --- a/Tests/Functional/Bundle/TestBundle/TestBundle.php +++ b/Tests/Functional/Bundle/TestBundle/TestBundle.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle; -use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\AnnotationReaderPass; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\Config\CustomConfig; use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; use Symfony\Component\DependencyInjection\Compiler\PassConfig; From cc44af547af0c86fdf0983f10b1e9f67ae4899a2 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 11 Sep 2023 14:26:06 +0200 Subject: [PATCH 021/180] Drop support for Twig 2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 75cd73795..818f4aa50 100644 --- a/composer.json +++ b/composer.json @@ -70,7 +70,7 @@ "symfony/uid": "^6.4|^7.0", "symfony/web-link": "^6.4|^7.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^2.10|^3.0" + "twig/twig": "^3.0.4" }, "conflict": { "doctrine/persistence": "<1.3", From 4633b156b60cac478f6e40db3128c98b25144fa4 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 5 Oct 2023 16:34:22 +0200 Subject: [PATCH 022/180] [FrameworkBundle] Remove ContainerAware leftover --- Tests/Fixtures/ContainerAwareController.php | 38 --------------------- 1 file changed, 38 deletions(-) delete mode 100644 Tests/Fixtures/ContainerAwareController.php diff --git a/Tests/Fixtures/ContainerAwareController.php b/Tests/Fixtures/ContainerAwareController.php deleted file mode 100644 index fa1be2069..000000000 --- a/Tests/Fixtures/ContainerAwareController.php +++ /dev/null @@ -1,38 +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\Fixtures; - -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -class ContainerAwareController implements ContainerAwareInterface -{ - private ?ContainerInterface $container = null; - - public function setContainer(?ContainerInterface $container): void - { - $this->container = $container; - } - - public function getContainer(): ?ContainerInterface - { - return $this->container; - } - - public function testAction() - { - } - - public function __invoke() - { - } -} From 6fd189fb38c7a8460bf7600aa5290bb97abd2590 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sat, 14 Oct 2023 14:52:14 +0200 Subject: [PATCH 023/180] [FrameworkBundle] Remove deprecation layer for `KernelBrowser::loginUser()` --- KernelBrowser.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/KernelBrowser.php b/KernelBrowser.php index cf6df7009..0c1374633 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -100,10 +100,8 @@ public function enableReboot(): void * * @return $this */ - public function loginUser(object $user, string $firewallContext = 'main'/* , array $tokenAttributes = [] */): static + public function loginUser(object $user, string $firewallContext = 'main', array $tokenAttributes = []): static { - $tokenAttributes = 2 < \func_num_args() ? func_get_arg(2) : []; - if (!interface_exists(UserInterface::class)) { throw new \LogicException(sprintf('"%s" requires symfony/security-core to be installed. Try running "composer require symfony/security-core".', __METHOD__)); } From 4639f4f3f408218811d5fa7c801e5c7a9506a3f2 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 17 Oct 2023 16:30:56 +0200 Subject: [PATCH 024/180] [Serializer] Fix Serializer deprecations merge --- DependencyInjection/FrameworkExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index cfb3b756b..507e26107 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1858,9 +1858,9 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $serializerLoaders = []; if (isset($config['enable_attributes']) && $config['enable_attributes']) { - $annotationLoader = new Definition(AttributeLoader::class); + $attributeLoader = new Definition(AttributeLoader::class); - $serializerLoaders[] = $annotationLoader; + $serializerLoaders[] = $attributeLoader; } $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { From 0590b338671130b345f63139390c83e405588eb2 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 18 Oct 2023 11:51:14 +0200 Subject: [PATCH 025/180] [FrameworkBundle][Routing] Remove remaining deprecations --- CHANGELOG.md | 4 ++++ Resources/config/routing.php | 9 --------- Routing/AttributeRouteControllerLoader.php | 8 +------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c71b9e56e..997d79422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ CHANGELOG * Make the `framework.validation.email_validation_mode` config option default to `html5` * Remove the `framework.validation.enable_annotations` config option, use `framework.validation.enable_attributes` instead * Remove the `framework.serializer.enable_annotations` config option, use `framework.serializer.enable_attributes` instead + * Remove the `routing.loader.annotation` service, use the `routing.loader.attribute` service instead + * Remove the `routing.loader.annotation.directory` service, use the `routing.loader.attribute.directory` service instead + * Remove the `routing.loader.annotation.file` service, use the `routing.loader.attribute.file` service instead + * Remove `AnnotatedRouteControllerLoader`, use `AttributeRouteControllerLoader` instead 6.4 --- diff --git a/Resources/config/routing.php b/Resources/config/routing.php index 5fc0cbb3e..8cdbbf33a 100644 --- a/Resources/config/routing.php +++ b/Resources/config/routing.php @@ -98,9 +98,6 @@ ]) ->tag('routing.loader', ['priority' => -10]) - ->alias('routing.loader.annotation', 'routing.loader.attribute') - ->deprecate('symfony/routing', '6.4', 'The "%alias_id%" service is deprecated, use the "routing.loader.attribute" service instead.') - ->set('routing.loader.attribute.directory', AttributeDirectoryLoader::class) ->args([ service('file_locator'), @@ -108,9 +105,6 @@ ]) ->tag('routing.loader', ['priority' => -10]) - ->alias('routing.loader.annotation.directory', 'routing.loader.attribute.directory') - ->deprecate('symfony/routing', '6.4', 'The "%alias_id%" service is deprecated, use the "routing.loader.attribute.directory" service instead.') - ->set('routing.loader.attribute.file', AttributeFileLoader::class) ->args([ service('file_locator'), @@ -118,9 +112,6 @@ ]) ->tag('routing.loader', ['priority' => -10]) - ->alias('routing.loader.annotation.file', 'routing.loader.attribute.file') - ->deprecate('symfony/routing', '6.4', 'The "%alias_id%" service is deprecated, use the "routing.loader.attribute.file" service instead.') - ->set('routing.loader.psr4', Psr4DirectoryLoader::class) ->args([ service('file_locator'), diff --git a/Routing/AttributeRouteControllerLoader.php b/Routing/AttributeRouteControllerLoader.php index a629f4387..7e43e1af5 100644 --- a/Routing/AttributeRouteControllerLoader.php +++ b/Routing/AttributeRouteControllerLoader.php @@ -25,10 +25,8 @@ class AttributeRouteControllerLoader extends AttributeClassLoader { /** * Configures the _controller default parameter of a given Route instance. - * - * @return void */ - protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot) + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot): void { if ('__invoke' === $method->getName()) { $route->setDefault('_controller', $class->getName()); @@ -51,7 +49,3 @@ protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMetho return str_replace('__', '_', $name); } } - -if (!class_exists(AnnotatedRouteControllerLoader::class, false)) { - class_alias(AttributeRouteControllerLoader::class, AnnotatedRouteControllerLoader::class); -} From 1edaef6271e26f799ab71d3eda0295ef21304f1f Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 18 Oct 2023 13:21:23 +0200 Subject: [PATCH 026/180] [FrameworkBundle] Fix workflow tests --- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 6e94638e0..ec939b4b8 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -505,7 +505,7 @@ public function testWorkflowServicesCanBeEnabled() { $container = $this->createContainerFromFile('workflows_enabled'); - $this->assertTrue($container->hasDefinition('.workflow.registry')); + $this->assertTrue($container->hasDefinition('workflow.registry')); $this->assertTrue($container->hasDefinition('console.command.workflow_dump')); } From bfad70a13278b54286d997de1b9502d21f313937 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 18 Oct 2023 14:57:55 +0200 Subject: [PATCH 027/180] [7.0] Cleanup legacy code paths --- CacheWarmer/SerializerCacheWarmer.php | 3 --- CacheWarmer/ValidatorCacheWarmer.php | 3 --- DependencyInjection/Configuration.php | 3 --- DependencyInjection/FrameworkExtension.php | 8 -------- FrameworkBundle.php | 7 +------ Resources/config/cache.php | 5 ----- Resources/config/services.php | 3 --- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 3 --- Tests/Test/WebTestCaseTest.php | 9 --------- 9 files changed, 1 insertion(+), 43 deletions(-) diff --git a/CacheWarmer/SerializerCacheWarmer.php b/CacheWarmer/SerializerCacheWarmer.php index 1fd257d27..b1300516b 100644 --- a/CacheWarmer/SerializerCacheWarmer.php +++ b/CacheWarmer/SerializerCacheWarmer.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; -use Doctrine\Common\Annotations\AnnotationException; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; @@ -51,8 +50,6 @@ protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, string foreach ($loader->getMappedClasses() as $mappedClass) { try { $metadataFactory->getMetadataFor($mappedClass); - } catch (AnnotationException) { - // ignore failing annotations } catch (\Exception $e) { $this->ignoreAutoloadException($mappedClass, $e); } diff --git a/CacheWarmer/ValidatorCacheWarmer.php b/CacheWarmer/ValidatorCacheWarmer.php index e37b0196a..d88fd36c8 100644 --- a/CacheWarmer/ValidatorCacheWarmer.php +++ b/CacheWarmer/ValidatorCacheWarmer.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; -use Doctrine\Common\Annotations\AnnotationException; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; @@ -50,8 +49,6 @@ protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, string if ($metadataFactory->hasMetadataFor($mappedClass)) { $metadataFactory->getMetadataFor($mappedClass); } - } catch (AnnotationException) { - // ignore failing annotations } catch (\Exception $e) { $this->ignoreAutoloadException($mappedClass, $e); } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index df58d7392..d5a09481c 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -899,9 +899,6 @@ private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $ ->info('The directory to store JavaScript vendors.') ->defaultValue('%kernel.project_dir%/assets/vendor') ->end() - ->scalarNode('provider') - ->setDeprecated('symfony/framework-bundle', '6.4', 'Option "%node%" at "%path%" is deprecated and does nothing. Remove it.') - ->end() ->end() ->end() ->end() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 574f40c45..b126a2faf 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -564,14 +564,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerHtmlSanitizerConfiguration($config['html_sanitizer'], $container, $loader); } - $this->addAnnotatedClassesToCompile([ - '**\\Controller\\', - '**\\Entity\\', - - // Added explicitly so that we don't rely on the class map being dumped to make it work - AbstractController::class, - ]); - if (ContainerBuilder::willBeAvailable('symfony/mime', MimeTypes::class, ['symfony/framework-bundle'])) { $loader->load('mime_type.php'); } diff --git a/FrameworkBundle.php b/FrameworkBundle.php index 3da66702c..701443723 100644 --- a/FrameworkBundle.php +++ b/FrameworkBundle.php @@ -95,12 +95,7 @@ public function boot(): void $handler = ErrorHandler::register(null, false); - // When upgrading an existing Symfony application from 6.2 to 6.3, and - // the cache is warmed up, the service is not available yet, so we need - // to check if it exists. - if ($this->container->has('debug.error_handler_configurator')) { - $this->container->get('debug.error_handler_configurator')->configure($handler); - } + $this->container->get('debug.error_handler_configurator')->configure($handler); if ($this->container->getParameter('kernel.http_method_override')) { Request::enableHttpMethodParameterOverride(); diff --git a/Resources/config/cache.php b/Resources/config/cache.php index 87207cf95..eceb9bdfd 100644 --- a/Resources/config/cache.php +++ b/Resources/config/cache.php @@ -56,11 +56,6 @@ ->private() ->tag('cache.pool') - ->set('cache.annotations') - ->parent('cache.system') - ->private() - ->tag('cache.pool') - ->set('cache.property_info') ->parent('cache.system') ->private() diff --git a/Resources/config/services.php b/Resources/config/services.php index 905e16f9b..c85ccf5d0 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -48,7 +48,6 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\HttpKernel\UriSigner as HttpKernelUriSigner; use Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner; use Symfony\Component\Runtime\Runner\Symfony\ResponseRunner; use Symfony\Component\Runtime\SymfonyRuntime; @@ -158,8 +157,6 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] param('kernel.secret'), ]) ->alias(UriSigner::class, 'uri_signer') - ->alias(HttpKernelUriSigner::class, 'uri_signer') - ->deprecate('symfony/framework-bundle', '6.4', 'The "%alias_id%" alias is deprecated, use "'.UriSigner::class.'" instead.') ->set('config_cache_factory', ResourceCheckerConfigCacheFactory::class) ->args([ diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index ec939b4b8..575ed5666 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; @@ -91,8 +90,6 @@ abstract class FrameworkExtensionTestCase extends TestCase { - use ExpectDeprecationTrait; - private static array $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); diff --git a/Tests/Test/WebTestCaseTest.php b/Tests/Test/WebTestCaseTest.php index d9f597044..54a8044b0 100644 --- a/Tests/Test/WebTestCaseTest.php +++ b/Tests/Test/WebTestCaseTest.php @@ -23,7 +23,6 @@ use Symfony\Component\HttpFoundation\Cookie as HttpFoundationCookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHeaderLocationSame; class WebTestCaseTest extends TestCase { @@ -62,10 +61,6 @@ public function testAssertResponseRedirectsWithLocation() public function testAssertResponseRedirectsWithLocationWithoutHost() { - if (!class_exists(ResponseHeaderLocationSame::class)) { - $this->markTestSkipped('Requires symfony/http-foundation 6.3 or higher.'); - } - $this->getResponseTester(new Response('', 301, ['Location' => 'https://example.com/']))->assertResponseRedirects('/'); $this->expectException(AssertionFailedError::class); $this->expectExceptionMessage('is redirected and has header "Location" matching "/".'); @@ -74,10 +69,6 @@ public function testAssertResponseRedirectsWithLocationWithoutHost() public function testAssertResponseRedirectsWithLocationWithoutScheme() { - if (!class_exists(ResponseHeaderLocationSame::class)) { - $this->markTestSkipped('Requires symfony/http-foundation 6.3 or higher.'); - } - $this->getResponseTester(new Response('', 301, ['Location' => 'https://example.com/']))->assertResponseRedirects('//example.com/'); $this->expectException(AssertionFailedError::class); $this->expectExceptionMessage('is redirected and has header "Location" matching "//example.com/".'); From 84b4769da2bac6ec14c44ee8fe98d7ea409fb1a6 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 19 Oct 2023 18:37:23 +0200 Subject: [PATCH 028/180] [FrameworkBundle] Remove deprecated compiler passes --- CHANGELOG.md | 4 + .../AddExpressionLanguageProvidersPass.php | 39 ------ .../Compiler/DataCollectorTranslatorPass.php | 40 ------ .../Compiler/LoggingTranslatorPass.php | 58 -------- .../Compiler/WorkflowGuardListenerPass.php | 49 ------- ...AddExpressionLanguageProvidersPassTest.php | 63 --------- .../DataCollectorTranslatorPassTest.php | 124 ------------------ .../Compiler/LoggingTranslatorPassTest.php | 85 ------------ .../WorkflowGuardListenerPassTest.php | 106 --------------- 9 files changed, 4 insertions(+), 564 deletions(-) delete mode 100644 DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php delete mode 100644 DependencyInjection/Compiler/DataCollectorTranslatorPass.php delete mode 100644 DependencyInjection/Compiler/LoggingTranslatorPass.php delete mode 100644 DependencyInjection/Compiler/WorkflowGuardListenerPass.php delete mode 100644 Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php delete mode 100644 Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php delete mode 100644 Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php delete mode 100644 Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ea10516..ed3b53d14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,10 @@ CHANGELOG * Remove the `routing.loader.annotation.directory` service, use the `routing.loader.attribute.directory` service instead * Remove the `routing.loader.annotation.file` service, use the `routing.loader.attribute.file` service instead * Remove `AnnotatedRouteControllerLoader`, use `AttributeRouteControllerLoader` instead + * Remove `AddExpressionLanguageProvidersPass`, use `Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass` instead + * Remove `DataCollectorTranslatorPass`, use `Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass` instead + * Remove `LoggingTranslatorPass`, use `Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass` instead + * Remove `WorkflowGuardListenerPass`, use `Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass` instead 6.4 --- diff --git a/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php deleted file mode 100644 index cc8871b6b..000000000 --- a/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php +++ /dev/null @@ -1,39 +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\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', AddExpressionLanguageProvidersPass::class, \Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass::class); - -/** - * Registers the expression language providers. - * - * @author Fabien Potencier - * - * @deprecated since Symfony 6.4, use Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass instead. - */ -class AddExpressionLanguageProvidersPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - // routing - if ($container->has('router.default')) { - $definition = $container->findDefinition('router.default'); - foreach ($container->findTaggedServiceIds('routing.expression_language_provider', true) as $id => $attributes) { - $definition->addMethodCall('addExpressionLanguageProvider', [new Reference($id)]); - } - } - } -} diff --git a/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/DependencyInjection/Compiler/DataCollectorTranslatorPass.php deleted file mode 100644 index f87dcc277..000000000 --- a/DependencyInjection/Compiler/DataCollectorTranslatorPass.php +++ /dev/null @@ -1,40 +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\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\Translation\TranslatorBagInterface; - -trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', DataCollectorTranslatorPass::class, \Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass::class); - -/** - * @author Christian Flothmann - * - * @deprecated since Symfony 6.4, use Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass instead. - */ -class DataCollectorTranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (!$container->has('translator')) { - return; - } - - $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); - - if (!is_subclass_of($translatorClass, TranslatorBagInterface::class)) { - $container->removeDefinition('translator.data_collector'); - $container->removeDefinition('data_collector.translation'); - } - } -} diff --git a/DependencyInjection/Compiler/LoggingTranslatorPass.php b/DependencyInjection/Compiler/LoggingTranslatorPass.php deleted file mode 100644 index c88643132..000000000 --- a/DependencyInjection/Compiler/LoggingTranslatorPass.php +++ /dev/null @@ -1,58 +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\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', LoggingTranslatorPass::class, \Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass::class); - -/** - * @author Abdellatif Ait boudad - * - * @deprecated since Symfony 6.4, use Symfony\Component\Translation\DependencyInjection\LoggingTranslatorPass instead. - */ -class LoggingTranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) { - return; - } - - if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) { - $translatorAlias = $container->getAlias('translator'); - $definition = $container->getDefinition((string) $translatorAlias); - $class = $container->getParameterBag()->resolveValue($definition->getClass()); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias)); - } - if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) { - $container->getDefinition('translator.logging')->setDecoratedService('translator'); - $warmer = $container->getDefinition('translation.warmer'); - $subscriberAttributes = $warmer->getTag('container.service_subscriber'); - $warmer->clearTag('container.service_subscriber'); - - foreach ($subscriberAttributes as $k => $v) { - if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) { - $warmer->addTag('container.service_subscriber', $v); - } - } - $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']); - } - } - } -} diff --git a/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/DependencyInjection/Compiler/WorkflowGuardListenerPass.php deleted file mode 100644 index e66d9503d..000000000 --- a/DependencyInjection/Compiler/WorkflowGuardListenerPass.php +++ /dev/null @@ -1,49 +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\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; - -trigger_deprecation('symfony/framework-bundle', '6.4', 'The "%s" class is deprecated, use "%s" instead.', WorkflowGuardListenerPass::class, \Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass::class); - -/** - * @author Christian Flothmann - * @author Grégoire Pineau - * - * @deprecated since Symfony 6.4, use Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass instead. - */ -class WorkflowGuardListenerPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (!$container->hasParameter('workflow.has_guard_listeners')) { - return; - } - - $container->getParameterBag()->remove('workflow.has_guard_listeners'); - - $servicesNeeded = [ - 'security.token_storage', - 'security.authorization_checker', - 'security.authentication.trust_resolver', - 'security.role_hierarchy', - ]; - - foreach ($servicesNeeded as $service) { - if (!$container->has($service)) { - throw new LogicException(sprintf('The "%s" service is needed to be able to use the workflow guard listener.', $service)); - } - } - } -} diff --git a/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php b/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php deleted file mode 100644 index d159057c6..000000000 --- a/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php +++ /dev/null @@ -1,63 +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\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @group legacy - */ -class AddExpressionLanguageProvidersPassTest extends TestCase -{ - public function testProcessForRouter() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddExpressionLanguageProvidersPass()); - - $definition = new Definition(\stdClass::class); - $definition->addTag('routing.expression_language_provider'); - $container->setDefinition('some_routing_provider', $definition->setPublic(true)); - - $container->register('router.default', \stdClass::class)->setPublic(true); - $container->compile(); - - $router = $container->getDefinition('router.default'); - $calls = $router->getMethodCalls(); - $this->assertCount(1, $calls); - $this->assertEquals('addExpressionLanguageProvider', $calls[0][0]); - $this->assertEquals(new Reference('some_routing_provider'), $calls[0][1][0]); - } - - public function testProcessForRouterAlias() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddExpressionLanguageProvidersPass()); - - $definition = new Definition(\stdClass::class); - $definition->addTag('routing.expression_language_provider'); - $container->setDefinition('some_routing_provider', $definition->setPublic(true)); - - $container->register('my_router', \stdClass::class)->setPublic(true); - $container->setAlias('router.default', 'my_router'); - $container->compile(); - - $router = $container->getDefinition('my_router'); - $calls = $router->getMethodCalls(); - $this->assertCount(1, $calls); - $this->assertEquals('addExpressionLanguageProvider', $calls[0][0]); - $this->assertEquals(new Reference('some_routing_provider'), $calls[0][1][0]); - } -} diff --git a/Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php b/Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php deleted file mode 100644 index 805f2ca84..000000000 --- a/Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php +++ /dev/null @@ -1,124 +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\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Translation\DataCollector\TranslationDataCollector; -use Symfony\Component\Translation\DataCollectorTranslator; -use Symfony\Component\Translation\Translator; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @group legacy - */ -class DataCollectorTranslatorPassTest extends TestCase -{ - private ContainerBuilder $container; - private DataCollectorTranslatorPass $dataCollectorTranslatorPass; - - protected function setUp(): void - { - $this->container = new ContainerBuilder(); - $this->dataCollectorTranslatorPass = new DataCollectorTranslatorPass(); - - $this->container->setParameter('translator_implementing_bag', Translator::class); - $this->container->setParameter('translator_not_implementing_bag', 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TranslatorWithTranslatorBag'); - - $this->container->register('translator.data_collector', DataCollectorTranslator::class) - ->setDecoratedService('translator') - ->setArguments([new Reference('translator.data_collector.inner')]) - ; - - $this->container->register('data_collector.translation', TranslationDataCollector::class) - ->setArguments([new Reference('translator.data_collector')]) - ; - } - - /** - * @dataProvider getImplementingTranslatorBagInterfaceTranslatorClassNames - */ - public function testProcessKeepsDataCollectorTranslatorIfItImplementsTranslatorBagInterface($class) - { - $this->container->register('translator', $class); - - $this->dataCollectorTranslatorPass->process($this->container); - - $this->assertTrue($this->container->hasDefinition('translator.data_collector')); - } - - /** - * @dataProvider getImplementingTranslatorBagInterfaceTranslatorClassNames - */ - public function testProcessKeepsDataCollectorIfTranslatorImplementsTranslatorBagInterface($class) - { - $this->container->register('translator', $class); - - $this->dataCollectorTranslatorPass->process($this->container); - - $this->assertTrue($this->container->hasDefinition('data_collector.translation')); - } - - public static function getImplementingTranslatorBagInterfaceTranslatorClassNames() - { - return [ - [Translator::class], - ['%translator_implementing_bag%'], - ]; - } - - /** - * @dataProvider getNotImplementingTranslatorBagInterfaceTranslatorClassNames - */ - public function testProcessRemovesDataCollectorTranslatorIfItDoesNotImplementTranslatorBagInterface($class) - { - $this->container->register('translator', $class); - - $this->dataCollectorTranslatorPass->process($this->container); - - $this->assertFalse($this->container->hasDefinition('translator.data_collector')); - } - - /** - * @dataProvider getNotImplementingTranslatorBagInterfaceTranslatorClassNames - */ - public function testProcessRemovesDataCollectorIfTranslatorDoesNotImplementTranslatorBagInterface($class) - { - $this->container->register('translator', $class); - - $this->dataCollectorTranslatorPass->process($this->container); - - $this->assertFalse($this->container->hasDefinition('data_collector.translation')); - } - - public static function getNotImplementingTranslatorBagInterfaceTranslatorClassNames() - { - return [ - ['Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TranslatorWithTranslatorBag'], - ['%translator_not_implementing_bag%'], - ]; - } -} - -class TranslatorWithTranslatorBag implements TranslatorInterface -{ - public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string - { - } - - public function getLocale(): string - { - return 'en'; - } -} diff --git a/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php b/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php deleted file mode 100644 index e15c62207..000000000 --- a/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php +++ /dev/null @@ -1,85 +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\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Translation\Translator; - -/** - * @group legacy - */ -class LoggingTranslatorPassTest extends TestCase -{ - public function testProcess() - { - $container = new ContainerBuilder(); - $container->setParameter('translator.logging', true); - $container->setParameter('translator.class', Translator::class); - $container->register('monolog.logger'); - $container->setAlias('logger', 'monolog.logger'); - $container->register('translator.default', '%translator.class%'); - $container->register('translator.logging', '%translator.class%'); - $container->setAlias('translator', 'translator.default'); - $translationWarmerDefinition = $container->register('translation.warmer') - ->addArgument(new Reference('translator')) - ->addTag('container.service_subscriber', ['id' => 'translator']) - ->addTag('container.service_subscriber', ['id' => 'foo']); - - $pass = new LoggingTranslatorPass(); - $pass->process($container); - - $this->assertEquals( - ['container.service_subscriber' => [ - ['id' => 'foo'], - ['key' => 'translator', 'id' => 'translator.logging.inner'], - ]], - $translationWarmerDefinition->getTags() - ); - } - - public function testThatCompilerPassIsIgnoredIfThereIsNotLoggerDefinition() - { - $container = new ContainerBuilder(); - $container->register('identity_translator'); - $container->setAlias('translator', 'identity_translator'); - - $definitionsBefore = \count($container->getDefinitions()); - $aliasesBefore = \count($container->getAliases()); - - $pass = new LoggingTranslatorPass(); - $pass->process($container); - - // the container is untouched (i.e. no new definitions or aliases) - $this->assertCount($definitionsBefore, $container->getDefinitions()); - $this->assertCount($aliasesBefore, $container->getAliases()); - } - - public function testThatCompilerPassIsIgnoredIfThereIsNotTranslatorDefinition() - { - $container = new ContainerBuilder(); - $container->register('monolog.logger'); - $container->setAlias('logger', 'monolog.logger'); - - $definitionsBefore = \count($container->getDefinitions()); - $aliasesBefore = \count($container->getAliases()); - - $pass = new LoggingTranslatorPass(); - $pass->process($container); - - // the container is untouched (i.e. no new definitions or aliases) - $this->assertCount($definitionsBefore, $container->getDefinitions()); - $this->assertCount($aliasesBefore, $container->getAliases()); - } -} diff --git a/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php b/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php deleted file mode 100644 index 4c3327847..000000000 --- a/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php +++ /dev/null @@ -1,106 +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\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use Symfony\Component\Security\Core\Role\RoleHierarchy; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * @group legacy - */ -class WorkflowGuardListenerPassTest extends TestCase -{ - private ContainerBuilder $container; - private WorkflowGuardListenerPass $compilerPass; - - protected function setUp(): void - { - $this->container = new ContainerBuilder(); - $this->compilerPass = new WorkflowGuardListenerPass(); - } - - public function testNoExeptionIfParameterIsNotSet() - { - $this->compilerPass->process($this->container); - - $this->assertFalse($this->container->hasParameter('workflow.has_guard_listeners')); - } - - public function testNoExeptionIfAllDependenciesArePresent() - { - $this->container->setParameter('workflow.has_guard_listeners', true); - $this->container->register('security.token_storage', TokenStorageInterface::class); - $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); - $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); - $this->container->register('security.role_hierarchy', RoleHierarchy::class); - $this->container->register('validator', ValidatorInterface::class); - - $this->compilerPass->process($this->container); - - $this->assertFalse($this->container->hasParameter('workflow.has_guard_listeners')); - } - - public function testExceptionIfTheTokenStorageServiceIsNotPresent() - { - $this->expectException(LogicException::class); - $this->expectExceptionMessage('The "security.token_storage" service is needed to be able to use the workflow guard listener.'); - $this->container->setParameter('workflow.has_guard_listeners', true); - $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); - $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); - $this->container->register('security.role_hierarchy', RoleHierarchy::class); - - $this->compilerPass->process($this->container); - } - - public function testExceptionIfTheAuthorizationCheckerServiceIsNotPresent() - { - $this->expectException(LogicException::class); - $this->expectExceptionMessage('The "security.authorization_checker" service is needed to be able to use the workflow guard listener.'); - $this->container->setParameter('workflow.has_guard_listeners', true); - $this->container->register('security.token_storage', TokenStorageInterface::class); - $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); - $this->container->register('security.role_hierarchy', RoleHierarchy::class); - - $this->compilerPass->process($this->container); - } - - public function testExceptionIfTheAuthenticationTrustResolverServiceIsNotPresent() - { - $this->expectException(LogicException::class); - $this->expectExceptionMessage('The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener.'); - $this->container->setParameter('workflow.has_guard_listeners', true); - $this->container->register('security.token_storage', TokenStorageInterface::class); - $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); - $this->container->register('security.role_hierarchy', RoleHierarchy::class); - - $this->compilerPass->process($this->container); - } - - public function testExceptionIfTheRoleHierarchyServiceIsNotPresent() - { - $this->expectException(LogicException::class); - $this->expectExceptionMessage('The "security.role_hierarchy" service is needed to be able to use the workflow guard listener.'); - $this->container->setParameter('workflow.has_guard_listeners', true); - $this->container->register('security.token_storage', TokenStorageInterface::class); - $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); - $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); - - $this->compilerPass->process($this->container); - } -} From 760202fc4712a069c7cddf03250e00f0d5cdeb95 Mon Sep 17 00:00:00 2001 From: Rafael Villa Verde Date: Fri, 1 Dec 2023 01:03:58 -0300 Subject: [PATCH 029/180] [Mailer] Add Azure bridge --- DependencyInjection/FrameworkExtension.php | 1 + 1 file changed, 1 insertion(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 95c8d8fa1..8272d24c7 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2559,6 +2559,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co } $classToServices = [ + 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', From ec947a0de683f4df726e0924569ced70ce8d1144 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 10 Dec 2023 13:04:21 +0100 Subject: [PATCH 030/180] fix registering the Azure transport factory service --- Resources/config/mailer_transports.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index 06c9632d8..b8f822738 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; +use Symfony\Component\Mailer\Bridge\Azure\Transport\AzureTransportFactory; use Symfony\Component\Mailer\Bridge\Brevo\Transport\BrevoTransportFactory; use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; use Symfony\Component\Mailer\Bridge\Infobip\Transport\InfobipTransportFactory; @@ -44,6 +45,10 @@ ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') + ->set('mailer.transport_factory.azure', AzureTransportFactory::class) + ->parent('mailer.transport_factory.abstract') + ->tag('mailer.transport_factory') + ->set('mailer.transport_factory.brevo', BrevoTransportFactory::class) ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') From f224c6198d229e1750c4eed336aee0bee51b08ab Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 11 Dec 2023 08:59:31 +0100 Subject: [PATCH 031/180] allow Twig 4 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8e879fd21..e847cb1ef 100644 --- a/composer.json +++ b/composer.json @@ -71,7 +71,7 @@ "symfony/uid": "^6.4|^7.0", "symfony/web-link": "^6.4|^7.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^3.0.4" + "twig/twig": "^3.0.4|^4.0" }, "conflict": { "doctrine/persistence": "<1.3", From 47b1f997d2d7aa3ff39dc0dc8d689fed277e37ec Mon Sep 17 00:00:00 2001 From: Quentin Devos <4972091+Okhoshi@users.noreply.github.com> Date: Sat, 9 Dec 2023 11:58:51 +0100 Subject: [PATCH 032/180] [FrameworkBundle] Move Router cache directory to `kernel.build_dir` --- CHANGELOG.md | 6 +++ CacheWarmer/RouterCacheWarmer.php | 4 ++ DependencyInjection/Configuration.php | 5 ++- Routing/Router.php | 8 +++- Tests/CacheWarmer/RouterCacheWarmerTest.php | 43 +++++++++++++++---- .../DependencyInjection/ConfigurationTest.php | 2 +- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed3b53d14..4bde9c2f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +7.1 +--- + + * Move the Router `cache_dir` to `kernel.build_dir` + * Deprecate the `router.cache_dir` config option + 7.0 --- diff --git a/CacheWarmer/RouterCacheWarmer.php b/CacheWarmer/RouterCacheWarmer.php index 2af9a2fe8..9dfa71c2c 100644 --- a/CacheWarmer/RouterCacheWarmer.php +++ b/CacheWarmer/RouterCacheWarmer.php @@ -36,6 +36,10 @@ public function __construct(ContainerInterface $container) public function warmUp(string $cacheDir, string $buildDir = null): array { + if (!$buildDir) { + return []; + } + $router = $this->container->get('router'); if ($router instanceof WarmableInterface) { diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index a247418a9..493835892 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -613,7 +613,10 @@ private function addRouterSection(ArrayNodeDefinition $rootNode): void ->children() ->scalarNode('resource')->isRequired()->end() ->scalarNode('type')->end() - ->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%')->end() + ->scalarNode('cache_dir') + ->defaultValue('%kernel.build_dir%') + ->setDeprecated('symfony/framework-bundle', '7.1', 'Setting the "%path%.%node%" configuration option is deprecated. It will be removed in version 8.0.') + ->end() ->scalarNode('default_uri') ->info('The default URI used to generate URLs in a non-HTTP context') ->defaultNull() diff --git a/Routing/Router.php b/Routing/Router.php index d6b1d57dc..b5b7567de 100644 --- a/Routing/Router.php +++ b/Routing/Router.php @@ -82,10 +82,14 @@ public function getRouteCollection(): RouteCollection public function warmUp(string $cacheDir, string $buildDir = null): array { + if (!$buildDir) { + return []; + } + $currentDir = $this->getOption('cache_dir'); - // force cache generation - $this->setOption('cache_dir', $cacheDir); + // force cache generation in build_dir + $this->setOption('cache_dir', $buildDir); $this->getMatcher(); $this->getGenerator(); diff --git a/Tests/CacheWarmer/RouterCacheWarmerTest.php b/Tests/CacheWarmer/RouterCacheWarmerTest.php index 727b566e1..7686b139f 100644 --- a/Tests/CacheWarmer/RouterCacheWarmerTest.php +++ b/Tests/CacheWarmer/RouterCacheWarmerTest.php @@ -19,36 +19,61 @@ class RouterCacheWarmerTest extends TestCase { - public function testWarmUpWithWarmebleInterface() + public function testWarmUpWithWarmableInterfaceWithBuildDir() { $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); - $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmebleInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); + $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); $routerCacheWarmer = new RouterCacheWarmer($containerMock); - $routerCacheWarmer->warmUp('/tmp'); - $routerMock->expects($this->any())->method('warmUp')->with('/tmp')->willReturn([]); + $routerCacheWarmer->warmUp('/tmp/cache', '/tmp/build'); + $routerMock->expects($this->any())->method('warmUp')->with('/tmp/cache', '/tmp/build')->willReturn([]); $this->addToAssertionCount(1); } - public function testWarmUpWithoutWarmebleInterface() + public function testWarmUpWithoutWarmableInterfaceWithBuildDir() { $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); - $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmebleInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); + $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); $routerCacheWarmer = new RouterCacheWarmer($containerMock); $this->expectException(\LogicException::class); $this->expectExceptionMessage('cannot be warmed up because it does not implement "Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface"'); - $routerCacheWarmer->warmUp('/tmp'); + $routerCacheWarmer->warmUp('/tmp/cache', '/tmp/build'); + } + + public function testWarmUpWithWarmableInterfaceWithoutBuildDir() + { + $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); + + $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); + $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); + $routerCacheWarmer = new RouterCacheWarmer($containerMock); + + $preload = $routerCacheWarmer->warmUp('/tmp'); + $routerMock->expects($this->never())->method('warmUp'); + self::assertSame([], $preload); + $this->addToAssertionCount(1); + } + + public function testWarmUpWithoutWarmableInterfaceWithoutBuildDir() + { + $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); + + $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); + $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); + $routerCacheWarmer = new RouterCacheWarmer($containerMock); + $preload = $routerCacheWarmer->warmUp('/tmp'); + self::assertSame([], $preload); } } -interface testRouterInterfaceWithWarmebleInterface extends RouterInterface, WarmableInterface +interface testRouterInterfaceWithWarmableInterface extends RouterInterface, WarmableInterface { } -interface testRouterInterfaceWithoutWarmebleInterface extends RouterInterface +interface testRouterInterfaceWithoutWarmableInterface extends RouterInterface { } diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 82d9b354f..d56cfa90d 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -634,7 +634,7 @@ protected static function getBundleDefaultConfig() 'https_port' => 443, 'strict_requirements' => true, 'utf8' => true, - 'cache_dir' => '%kernel.cache_dir%', + 'cache_dir' => '%kernel.build_dir%', ], 'session' => [ 'enabled' => false, From 6fd1ada231f9836b0bf711f40cf585df80818ce1 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 14 Dec 2023 11:03:37 +0100 Subject: [PATCH 033/180] Set `strict` parameter of `in_array` to true where possible --- Command/TranslationDebugCommand.php | 4 ++-- DependencyInjection/Compiler/UnusedTagsPass.php | 2 +- DependencyInjection/Configuration.php | 2 +- DependencyInjection/FrameworkExtension.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Command/TranslationDebugCommand.php b/Command/TranslationDebugCommand.php index 79a67847a..15544a90c 100644 --- a/Command/TranslationDebugCommand.php +++ b/Command/TranslationDebugCommand.php @@ -223,8 +223,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } - if (!\in_array(self::MESSAGE_UNUSED, $states) && $input->getOption('only-unused') - || !\in_array(self::MESSAGE_MISSING, $states) && $input->getOption('only-missing') + if (!\in_array(self::MESSAGE_UNUSED, $states, true) && $input->getOption('only-unused') + || !\in_array(self::MESSAGE_MISSING, $states, true) && $input->getOption('only-missing') ) { continue; } diff --git a/DependencyInjection/Compiler/UnusedTagsPass.php b/DependencyInjection/Compiler/UnusedTagsPass.php index 1d21c6b66..6f53e57f0 100644 --- a/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/DependencyInjection/Compiler/UnusedTagsPass.php @@ -110,7 +110,7 @@ public function process(ContainerBuilder $container): void foreach ($container->findUnusedTags() as $tag) { // skip known tags - if (\in_array($tag, self::KNOWN_TAGS)) { + if (\in_array($tag, self::KNOWN_TAGS, true)) { continue; } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 493835892..31dbc6f8d 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -435,7 +435,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void if (!\is_string($value)) { return true; } - if (class_exists(WorkflowEvents::class) && !\in_array($value, WorkflowEvents::ALIASES)) { + if (class_exists(WorkflowEvents::class) && !\in_array($value, WorkflowEvents::ALIASES, true)) { return true; } } diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index d160942f6..5ec5929be 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2179,7 +2179,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) ->addTag('messenger.receiver', [ 'alias' => $name, - 'is_failure_transport' => \in_array($name, $failureTransports), + 'is_failure_transport' => \in_array($name, $failureTransports, true), ] ) ; From fea90681521723d59d1b4d6d13fdfcedcec7d87d Mon Sep 17 00:00:00 2001 From: Nyholm Date: Thu, 14 Dec 2023 19:51:27 +0100 Subject: [PATCH 034/180] [Notifier] Add Bluesky notifier bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index d160942f6..c25327f3d 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2695,6 +2695,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 3feb1c080..f678e0588 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -22,6 +22,10 @@ ->abstract() ->args([service('event_dispatcher'), service('http_client')->ignoreOnInvalid()]) + ->set('notifier.transport_factory.bluesky', Bridge\Bluesky\BlueskyTransportFactory::class) + ->parent('notifier.transport_factory.abstract') + ->tag('chatter.transport_factory') + ->set('notifier.transport_factory.brevo', Bridge\Brevo\BrevoTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') From 59d2946cc46f0ccd1d0177491b2970cf7292a36e Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Fri, 15 Dec 2023 13:46:43 -0500 Subject: [PATCH 035/180] [RateLimiter][FrameworkBundle] add `rate_limiter` tag to rate limiter services --- CHANGELOG.md | 1 + DependencyInjection/FrameworkExtension.php | 3 ++- .../PhpFrameworkExtensionTest.php | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bde9c2f4..ed156fda3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Move the Router `cache_dir` to `kernel.build_dir` * Deprecate the `router.cache_dir` config option + * Add `rate_limiter` tags to rate limiter services 7.0 --- diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 8776bcb9c..d8e061ad1 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2860,7 +2860,8 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde // default configuration (when used by other DI extensions) $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter']; - $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')); + $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')) + ->addTag('rate_limiter', ['name' => $name]); if (null !== $limiterConfig['lock_factory']) { if (!interface_exists(LockInterface::class)) { diff --git a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index 53268ffd2..deac159b6 100644 --- a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -245,4 +245,24 @@ public function testRateLimiterLockFactory() $container->getDefinition('limiter.without_lock')->getArgument(2); } + + public function testRateLimiterIsTagged() + { + $container = $this->createContainerFromClosure(function (ContainerBuilder $container) { + $container->loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'lock' => true, + 'rate_limiter' => [ + 'first' => ['policy' => 'fixed_window', 'limit' => 10, 'interval' => '1 hour'], + 'second' => ['policy' => 'fixed_window', 'limit' => 10, 'interval' => '1 hour'], + ], + ]); + }); + + $this->assertSame('first', $container->getDefinition('limiter.first')->getTag('rate_limiter')[0]['name']); + $this->assertSame('second', $container->getDefinition('limiter.second')->getTag('rate_limiter')[0]['name']); + } } From 8e8e7f0dc022371a712022f56c0009b033bad8dd Mon Sep 17 00:00:00 2001 From: Farhad Safarov Date: Sat, 16 Dec 2023 00:21:18 +0300 Subject: [PATCH 036/180] [Notifier] Add Unifonic notifier bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 8776bcb9c..3b611c38f 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2760,6 +2760,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ NotifierBridge\TurboSms\TurboSmsTransport::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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index f678e0588..fd2952c50 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -66,6 +66,10 @@ ->parent('notifier.transport_factory.abstract') ->tag('chatter.transport_factory') + ->set('notifier.transport_factory.unifonic', Bridge\Unifonic\UnifonicTransportFactory::class) + ->parent('notifier.transport_factory.abstract') + ->tag('texter.transport_factory') + ->set('notifier.transport_factory.all-my-sms', Bridge\AllMySms\AllMySmsTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') From d73a168baf6f9c088a16c1d646300e025bbecf1e Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 8 Dec 2023 16:21:59 +0100 Subject: [PATCH 037/180] Use faster hashing algorithms when possible --- EventListener/ConsoleProfilerListener.php | 2 +- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EventListener/ConsoleProfilerListener.php b/EventListener/ConsoleProfilerListener.php index d3fc38106..19f0794d4 100644 --- a/EventListener/ConsoleProfilerListener.php +++ b/EventListener/ConsoleProfilerListener.php @@ -72,7 +72,7 @@ public function initialize(ConsoleCommandEvent $event): void return; } - $request->attributes->set('_stopwatch_token', substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); + $request->attributes->set('_stopwatch_token', substr(hash('xxh128', uniqid(mt_rand(), true)), 0, 6)); $this->stopwatch->openSection(); } diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 460c899e3..4fa2ab34c 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1693,7 +1693,7 @@ public function testCachePoolServices() ->replaceArgument(0, $expectedSeed) ->replaceArgument(1, 12), (new ChildDefinition('cache.adapter.redis')) - ->replaceArgument(0, new Reference('.cache_connection.kYdiLgf')) + ->replaceArgument(0, new Reference('.cache_connection.U5HliuY')) ->replaceArgument(1, $expectedSeed) ->replaceArgument(2, 12), ], From c4ea5cf72130cf02e19a803fa9511ac3c9bc2ee1 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 18 Dec 2023 15:39:48 +0100 Subject: [PATCH 038/180] fix merge --- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 4fa2ab34c..4bd3c481f 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -40,6 +40,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -1693,7 +1694,7 @@ public function testCachePoolServices() ->replaceArgument(0, $expectedSeed) ->replaceArgument(1, 12), (new ChildDefinition('cache.adapter.redis')) - ->replaceArgument(0, new Reference('.cache_connection.U5HliuY')) + ->replaceArgument(0, new Reference('.cache_connection.'.(\count((new \ReflectionMethod(ContainerConfigurator::class, 'extension'))->getParameters()) > 2 ? 'U5HliuY' : 'kYdiLgf'))) ->replaceArgument(1, $expectedSeed) ->replaceArgument(2, 12), ], From 6e6f3cecf335ff50b26a5fbc0d22c09a5edf6591 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 18 Dec 2023 08:46:12 +0100 Subject: [PATCH 039/180] Code updates --- Console/Descriptor/JsonDescriptor.php | 2 +- Console/Descriptor/XmlDescriptor.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Console/Descriptor/JsonDescriptor.php b/Console/Descriptor/JsonDescriptor.php index 35c86c584..f3c70310e 100644 --- a/Console/Descriptor/JsonDescriptor.php +++ b/Console/Descriptor/JsonDescriptor.php @@ -323,7 +323,7 @@ private function getContainerAliasData(Alias $alias): array private function getEventDispatcherListenersData(EventDispatcherInterface $eventDispatcher, array $options): array { $data = []; - $event = \array_key_exists('event', $options) ? $options['event'] : null; + $event = $options['event'] ?? null; if (null !== $event) { foreach ($eventDispatcher->getListeners($event) as $listener) { diff --git a/Console/Descriptor/XmlDescriptor.php b/Console/Descriptor/XmlDescriptor.php index 069dcf09f..d530936d7 100644 --- a/Console/Descriptor/XmlDescriptor.php +++ b/Console/Descriptor/XmlDescriptor.php @@ -501,7 +501,7 @@ private function getContainerParameterDocument(mixed $parameter, ?array $depreca private function getEventDispatcherListenersDocument(EventDispatcherInterface $eventDispatcher, array $options): \DOMDocument { - $event = \array_key_exists('event', $options) ? $options['event'] : null; + $event = $options['event'] ?? null; $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher')); From 3191f9834cd4923c9c1ec077a4a2d48e24e9daf2 Mon Sep 17 00:00:00 2001 From: Alan ZARLI Date: Mon, 18 Dec 2023 14:48:00 +0100 Subject: [PATCH 040/180] [Notifier] Add Smsbox notifier bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 17330540d..f94430eeb 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2750,6 +2750,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index fd2952c50..a4a2574a2 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -188,6 +188,10 @@ ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') + ->set('notifier.transport_factory.smsbox', Bridge\Smsbox\SmsboxTransportFactory::class) + ->parent('notifier.transport_factory.abstract') + ->tag('texter.transport_factory') + ->set('notifier.transport_factory.smsc', Bridge\Smsc\SmscTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') From 089f2db00004e4b04b61ce15feee6260f8eb7b9d Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Tue, 26 Dec 2023 22:44:28 +0100 Subject: [PATCH 041/180] [Mailer][Notifier] Simplify transport service registration + sorting --- Resources/config/mailer_transports.php | 97 ++---- Resources/config/notifier_transports.php | 380 ++++++----------------- 2 files changed, 124 insertions(+), 353 deletions(-) diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index b8f822738..f95fc6d64 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -39,73 +39,32 @@ service('http_client')->ignoreOnInvalid(), service('logger')->ignoreOnInvalid(), ]) - ->tag('monolog.logger', ['channel' => 'mailer']) - - ->set('mailer.transport_factory.amazon', SesTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.azure', AzureTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.brevo', BrevoTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.gmail', GmailTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.infobip', InfobipTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailersend', MailerSendTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailchimp', MandrillTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailjet', MailjetTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailgun', MailgunTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailpace', MailPaceTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.postmark', PostmarkTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.sendgrid', SendgridTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.null', NullTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.scaleway', ScalewayTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.sendmail', SendmailTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory', ['priority' => -100]) - - ->set('mailer.transport_factory.native', NativeTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory'); + ->tag('monolog.logger', ['channel' => 'mailer']); + + $factories = [ + 'amazon' => SesTransportFactory::class, + 'azure' => AzureTransportFactory::class, + 'brevo' => BrevoTransportFactory::class, + 'gmail' => GmailTransportFactory::class, + 'infobip' => InfobipTransportFactory::class, + 'mailchimp' => MandrillTransportFactory::class, + 'mailersend' => MailerSendTransportFactory::class, + 'mailgun' => MailgunTransportFactory::class, + 'mailjet' => MailjetTransportFactory::class, + 'mailpace' => MailPaceTransportFactory::class, + 'native' => NativeTransportFactory::class, + 'null' => NullTransportFactory::class, + 'postmark' => PostmarkTransportFactory::class, + 'scaleway' => ScalewayTransportFactory::class, + 'sendgrid' => SendgridTransportFactory::class, + 'sendmail' => SendmailTransportFactory::class, + 'smtp' => EsmtpTransportFactory::class, + ]; + + foreach ($factories as $name => $class) { + $container->services() + ->set('mailer.transport_factory.'.$name, $class) + ->parent('mailer.transport_factory.abstract') + ->tag('mailer.transport_factory'); + } }; diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index a4a2574a2..fbe52abc2 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -20,156 +20,103 @@ ->set('notifier.transport_factory.abstract', AbstractTransportFactory::class) ->abstract() - ->args([service('event_dispatcher'), service('http_client')->ignoreOnInvalid()]) - - ->set('notifier.transport_factory.bluesky', Bridge\Bluesky\BlueskyTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.brevo', Bridge\Brevo\BrevoTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.slack', Bridge\Slack\SlackTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.linked-in', Bridge\LinkedIn\LinkedInTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.telegram', Bridge\Telegram\TelegramTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.mattermost', Bridge\Mattermost\MattermostTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.vonage', Bridge\Vonage\VonageTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.rocket-chat', Bridge\RocketChat\RocketChatTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.google-chat', Bridge\GoogleChat\GoogleChatTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.twilio', Bridge\Twilio\TwilioTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.twitter', Bridge\Twitter\TwitterTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.unifonic', Bridge\Unifonic\UnifonicTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.all-my-sms', Bridge\AllMySms\AllMySmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.firebase', Bridge\Firebase\FirebaseTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.forty-six-elks', Bridge\FortySixElks\FortySixElksTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.free-mobile', Bridge\FreeMobile\FreeMobileTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.spot-hit', Bridge\SpotHit\SpotHitTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.fake-chat', Bridge\FakeChat\FakeChatTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.fake-sms', Bridge\FakeSms\FakeSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.ovh-cloud', Bridge\OvhCloud\OvhCloudTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sinch', Bridge\Sinch\SinchTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.zulip', Bridge\Zulip\ZulipTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.infobip', Bridge\Infobip\InfobipTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.isendpro', Bridge\Isendpro\IsendproTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.mobyt', Bridge\Mobyt\MobytTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.smsapi', Bridge\Smsapi\SmsapiTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.esendex', Bridge\Esendex\EsendexTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sendberry', Bridge\Sendberry\SendberryTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.iqsms', Bridge\Iqsms\IqsmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.octopush', Bridge\Octopush\OctopushTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.discord', Bridge\Discord\DiscordTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.microsoft-teams', Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.gateway-api', Bridge\GatewayApi\GatewayApiTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.mercure', Bridge\Mercure\MercureTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.gitter', Bridge\Gitter\GitterTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.clickatell', Bridge\Clickatell\ClickatellTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.contact-everyone', Bridge\ContactEveryone\ContactEveryoneTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') + ->args([ + service('event_dispatcher'), + service('http_client')->ignoreOnInvalid(), + ]); + + $chatterFactories = [ + 'google-chat' => Bridge\GoogleChat\GoogleChatTransportFactory::class, + 'telegram' => Bridge\Telegram\TelegramTransportFactory::class, + 'bluesky' => Bridge\Bluesky\BlueskyTransportFactory::class, + 'fake-chat' => Bridge\FakeChat\FakeChatTransportFactory::class, + 'firebase' => Bridge\Firebase\FirebaseTransportFactory::class, + 'gitter' => Bridge\Gitter\GitterTransportFactory::class, + 'line-notify' => Bridge\LineNotify\LineNotifyTransportFactory::class, + 'linked-in' => Bridge\LinkedIn\LinkedInTransportFactory::class, + 'mastodon' => Bridge\Mastodon\MastodonTransportFactory::class, + 'mercure' => Bridge\Mercure\MercureTransportFactory::class, + 'microsoft-teams' => Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class, + 'pager-duty' => Bridge\PagerDuty\PagerDutyTransportFactory::class, + 'rocket-chat' => Bridge\RocketChat\RocketChatTransportFactory::class, + 'twitter' => Bridge\Twitter\TwitterTransportFactory::class, + 'zulip' => Bridge\Zulip\ZulipTransportFactory::class, + 'brevo' => Bridge\Brevo\BrevoTransportFactory::class, + 'chatwork' => Bridge\Chatwork\ChatworkTransportFactory::class, + 'discord' => Bridge\Discord\DiscordTransportFactory::class, + 'mattermost' => Bridge\Mattermost\MattermostTransportFactory::class, + 'slack' => Bridge\Slack\SlackTransportFactory::class, + 'zendesk' => Bridge\Zendesk\ZendeskTransportFactory::class, + ]; + + foreach ($chatterFactories as $name => $class) { + $container->services() + ->set('notifier.transport_factory.'.$name, $class) + ->parent('notifier.transport_factory.abstract') + ->tag('chatter.transport_factory'); + } + + $texterFactories = [ + 'all-my-sms' => Bridge\AllMySms\AllMySmsTransportFactory::class, + 'bandwidth' => Bridge\Bandwidth\BandwidthTransportFactory::class, + 'click-send' => Bridge\ClickSend\ClickSendTransportFactory::class, + 'clickatell' => Bridge\Clickatell\ClickatellTransportFactory::class, + 'contact-everyone' => Bridge\ContactEveryone\ContactEveryoneTransportFactory::class, + 'engagespot' => Bridge\Engagespot\EngagespotTransportFactory::class, + 'esendex' => Bridge\Esendex\EsendexTransportFactory::class, + 'expo' => Bridge\Expo\ExpoTransportFactory::class, + 'fake-sms' => Bridge\FakeSms\FakeSmsTransportFactory::class, + 'forty-six-elks' => Bridge\FortySixElks\FortySixElksTransportFactory::class, + 'free-mobile' => Bridge\FreeMobile\FreeMobileTransportFactory::class, + 'gateway-api' => Bridge\GatewayApi\GatewayApiTransportFactory::class, + 'go-ip' => Bridge\GoIp\GoIpTransportFactory::class, + 'infobip' => Bridge\Infobip\InfobipTransportFactory::class, + 'iqsms' => Bridge\Iqsms\IqsmsTransportFactory::class, + 'isendpro' => Bridge\Isendpro\IsendproTransportFactory::class, + 'kaz-info-teh' => Bridge\KazInfoTeh\KazInfoTehTransportFactory::class, + 'mailjet' => Bridge\Mailjet\MailjetTransportFactory::class, + 'message-bird' => Bridge\MessageBird\MessageBirdTransportFactory::class, + 'message-media' => Bridge\MessageMedia\MessageMediaTransportFactory::class, + 'mobyt' => Bridge\Mobyt\MobytTransportFactory::class, + 'novu' => Bridge\Novu\NovuTransportFactory::class, + 'ntfy' => Bridge\Ntfy\NtfyTransportFactory::class, + 'octopush' => Bridge\Octopush\OctopushTransportFactory::class, + 'one-signal' => Bridge\OneSignal\OneSignalTransportFactory::class, + 'orange-sms' => Bridge\OrangeSms\OrangeSmsTransportFactory::class, + 'ovh-cloud' => Bridge\OvhCloud\OvhCloudTransportFactory::class, + 'plivo' => Bridge\Plivo\PlivoTransportFactory::class, + 'pushover' => Bridge\Pushover\PushoverTransportFactory::class, + 'redlink' => Bridge\Redlink\RedlinkTransportFactory::class, + 'ring-central' => Bridge\RingCentral\RingCentralTransportFactory::class, + 'sendberry' => Bridge\Sendberry\SendberryTransportFactory::class, + 'simple-textin' => Bridge\SimpleTextin\SimpleTextinTransportFactory::class, + 'sinch' => Bridge\Sinch\SinchTransportFactory::class, + 'sms-factor' => Bridge\SmsFactor\SmsFactorTransportFactory::class, + 'sms77' => Bridge\Sms77\Sms77TransportFactory::class, + 'smsapi' => Bridge\Smsapi\SmsapiTransportFactory::class, + 'smsc' => Bridge\Smsc\SmscTransportFactory::class, + 'smsmode' => Bridge\Smsmode\SmsmodeTransportFactory::class, + 'spot-hit' => Bridge\SpotHit\SpotHitTransportFactory::class, + 'telnyx' => Bridge\Telnyx\TelnyxTransportFactory::class, + 'termii' => Bridge\Termii\TermiiTransportFactory::class, + 'turbo-sms' => Bridge\TurboSms\TurboSmsTransportFactory::class, + 'twilio' => Bridge\Twilio\TwilioTransportFactory::class, + 'unifonic' => Bridge\Unifonic\UnifonicTransportFactory::class, + 'vonage' => Bridge\Vonage\VonageTransportFactory::class, + 'yunpian' => Bridge\Yunpian\YunpianTransportFactory::class, + 'light-sms' => Bridge\LightSms\LightSmsTransportFactory::class, + 'sms-biuras' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, + 'smsbox' => Bridge\Smsbox\SmsboxTransportFactory::class, + ]; + + foreach ($texterFactories as $name => $class) { + $container->services() + ->set('notifier.transport_factory.'.$name, $class) + ->parent('notifier.transport_factory.abstract') + ->tag('texter.transport_factory'); + } + $container->services() ->set('notifier.transport_factory.amazon-sns', Bridge\AmazonSns\AmazonSnsTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') @@ -179,140 +126,5 @@ ->parent('notifier.transport_factory.abstract') ->tag('chatter.transport_factory') ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.light-sms', Bridge\LightSms\LightSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sms-biuras', Bridge\SmsBiuras\SmsBiurasTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.smsbox', Bridge\Smsbox\SmsboxTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.smsc', Bridge\Smsc\SmscTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sms-factor', Bridge\SmsFactor\SmsFactorTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.message-bird', Bridge\MessageBird\MessageBirdTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.message-media', Bridge\MessageMedia\MessageMediaTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.telnyx', Bridge\Telnyx\TelnyxTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.mailjet', Bridge\Mailjet\MailjetTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.yunpian', Bridge\Yunpian\YunpianTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.turbo-sms', Bridge\TurboSms\TurboSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sms77', Bridge\Sms77\Sms77TransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.one-signal', Bridge\OneSignal\OneSignalTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.orange-sms', Bridge\OrangeSms\OrangeSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.expo', Bridge\Expo\ExpoTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.kaz-info-teh', Bridge\KazInfoTeh\KazInfoTehTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.engagespot', Bridge\Engagespot\EngagespotTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.zendesk', Bridge\Zendesk\ZendeskTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.chatwork', Bridge\Chatwork\ChatworkTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.termii', Bridge\Termii\TermiiTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.ring-central', Bridge\RingCentral\RingCentralTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.plivo', Bridge\Plivo\PlivoTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.bandwidth', Bridge\Bandwidth\BandwidthTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.line-notify', Bridge\LineNotify\LineNotifyTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.mastodon', Bridge\Mastodon\MastodonTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.pager-duty', Bridge\PagerDuty\PagerDutyTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.pushover', Bridge\Pushover\PushoverTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.simple-textin', Bridge\SimpleTextin\SimpleTextinTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.click-send', Bridge\ClickSend\ClickSendTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.smsmode', Bridge\Smsmode\SmsmodeTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.novu', Bridge\Novu\NovuTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.ntfy', Bridge\Ntfy\NtfyTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.redlink', Bridge\Redlink\RedlinkTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - ->set('notifier.transport_factory.go-ip', Bridge\GoIp\GoIpTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') ; }; From 67fc0dd6052228a4a0128335adc701f18ef25963 Mon Sep 17 00:00:00 2001 From: Dennis Fridrich Date: Sat, 9 Dec 2023 17:41:28 +0100 Subject: [PATCH 042/180] Add sms-sluzba.cz Notifier Bridge Fix #52975 --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index f94430eeb..d1e6aa073 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2754,6 +2754,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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\SpotHit\SpotHitTransportFactory::class => 'notifier.transport_factory.spot-hit', NotifierBridge\Telegram\TelegramTransportFactory::class => 'notifier.transport_factory.telegram', NotifierBridge\Telnyx\TelnyxTransportFactory::class => 'notifier.transport_factory.telnyx', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index fbe52abc2..94962e8f1 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -107,6 +107,7 @@ 'light-sms' => Bridge\LightSms\LightSmsTransportFactory::class, 'sms-biuras' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, 'smsbox' => Bridge\Smsbox\SmsboxTransportFactory::class, + 'sms-sluzba' => Bridge\SmsSluzba\SmsSluzbaTransportFactory::class, ]; foreach ($texterFactories as $name => $class) { From e7b31132415b7eb37e6a21cb2f801462b268b43a Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 28 Dec 2023 22:37:50 +0100 Subject: [PATCH 043/180] [Notifier] Sort factories --- Resources/config/notifier_transports.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 94962e8f1..39a44e278 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -26,27 +26,27 @@ ]); $chatterFactories = [ - 'google-chat' => Bridge\GoogleChat\GoogleChatTransportFactory::class, - 'telegram' => Bridge\Telegram\TelegramTransportFactory::class, 'bluesky' => Bridge\Bluesky\BlueskyTransportFactory::class, + 'brevo' => Bridge\Brevo\BrevoTransportFactory::class, + 'chatwork' => Bridge\Chatwork\ChatworkTransportFactory::class, + 'discord' => Bridge\Discord\DiscordTransportFactory::class, 'fake-chat' => Bridge\FakeChat\FakeChatTransportFactory::class, 'firebase' => Bridge\Firebase\FirebaseTransportFactory::class, 'gitter' => Bridge\Gitter\GitterTransportFactory::class, + 'google-chat' => Bridge\GoogleChat\GoogleChatTransportFactory::class, 'line-notify' => Bridge\LineNotify\LineNotifyTransportFactory::class, 'linked-in' => Bridge\LinkedIn\LinkedInTransportFactory::class, 'mastodon' => Bridge\Mastodon\MastodonTransportFactory::class, + 'mattermost' => Bridge\Mattermost\MattermostTransportFactory::class, 'mercure' => Bridge\Mercure\MercureTransportFactory::class, 'microsoft-teams' => Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class, 'pager-duty' => Bridge\PagerDuty\PagerDutyTransportFactory::class, 'rocket-chat' => Bridge\RocketChat\RocketChatTransportFactory::class, - 'twitter' => Bridge\Twitter\TwitterTransportFactory::class, - 'zulip' => Bridge\Zulip\ZulipTransportFactory::class, - 'brevo' => Bridge\Brevo\BrevoTransportFactory::class, - 'chatwork' => Bridge\Chatwork\ChatworkTransportFactory::class, - 'discord' => Bridge\Discord\DiscordTransportFactory::class, - 'mattermost' => Bridge\Mattermost\MattermostTransportFactory::class, 'slack' => Bridge\Slack\SlackTransportFactory::class, + 'telegram' => Bridge\Telegram\TelegramTransportFactory::class, + 'twitter' => Bridge\Twitter\TwitterTransportFactory::class, 'zendesk' => Bridge\Zendesk\ZendeskTransportFactory::class, + 'zulip' => Bridge\Zulip\ZulipTransportFactory::class, ]; foreach ($chatterFactories as $name => $class) { @@ -74,6 +74,7 @@ 'iqsms' => Bridge\Iqsms\IqsmsTransportFactory::class, 'isendpro' => Bridge\Isendpro\IsendproTransportFactory::class, 'kaz-info-teh' => Bridge\KazInfoTeh\KazInfoTehTransportFactory::class, + 'light-sms' => Bridge\LightSms\LightSmsTransportFactory::class, 'mailjet' => Bridge\Mailjet\MailjetTransportFactory::class, 'message-bird' => Bridge\MessageBird\MessageBirdTransportFactory::class, 'message-media' => Bridge\MessageMedia\MessageMediaTransportFactory::class, @@ -91,9 +92,12 @@ 'sendberry' => Bridge\Sendberry\SendberryTransportFactory::class, 'simple-textin' => Bridge\SimpleTextin\SimpleTextinTransportFactory::class, 'sinch' => Bridge\Sinch\SinchTransportFactory::class, + 'sms-biuras' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, 'sms-factor' => Bridge\SmsFactor\SmsFactorTransportFactory::class, + 'sms-sluzba' => Bridge\SmsSluzba\SmsSluzbaTransportFactory::class, 'sms77' => Bridge\Sms77\Sms77TransportFactory::class, 'smsapi' => Bridge\Smsapi\SmsapiTransportFactory::class, + 'smsbox' => Bridge\Smsbox\SmsboxTransportFactory::class, 'smsc' => Bridge\Smsc\SmscTransportFactory::class, 'smsmode' => Bridge\Smsmode\SmsmodeTransportFactory::class, 'spot-hit' => Bridge\SpotHit\SpotHitTransportFactory::class, @@ -104,10 +108,6 @@ 'unifonic' => Bridge\Unifonic\UnifonicTransportFactory::class, 'vonage' => Bridge\Vonage\VonageTransportFactory::class, 'yunpian' => Bridge\Yunpian\YunpianTransportFactory::class, - 'light-sms' => Bridge\LightSms\LightSmsTransportFactory::class, - 'sms-biuras' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, - 'smsbox' => Bridge\Smsbox\SmsboxTransportFactory::class, - 'sms-sluzba' => Bridge\SmsSluzba\SmsSluzbaTransportFactory::class, ]; foreach ($texterFactories as $name => $class) { From 595d82e7b043781af74030f2aa743c1720a53dff Mon Sep 17 00:00:00 2001 From: Frank Naegler Date: Fri, 8 Dec 2023 00:00:57 +0100 Subject: [PATCH 044/180] [Notifier] Add Seven Notifier Bridge Seven.io is the new name of SMS77, they changed also the URL to the gateway. To reflect that change, this patch introduces the new Seven Notifier Bridge. The current SMS77 Bridge should be deprecated in another patch --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index d1e6aa073..4750729ef 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2745,6 +2745,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ NotifierBridge\RocketChat\RocketChatTransportFactory::class => 'notifier.transport_factory.rocket-chat', NotifierBridge\Sendberry\SendberryTransportFactory::class => 'notifier.transport_factory.sendberry', 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 39a44e278..c92d9b4b6 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -90,6 +90,7 @@ 'redlink' => Bridge\Redlink\RedlinkTransportFactory::class, 'ring-central' => Bridge\RingCentral\RingCentralTransportFactory::class, 'sendberry' => Bridge\Sendberry\SendberryTransportFactory::class, + 'sevenio' => Bridge\Sevenio\SevenIoTransportFactory::class, 'simple-textin' => Bridge\SimpleTextin\SimpleTextinTransportFactory::class, 'sinch' => Bridge\Sinch\SinchTransportFactory::class, 'sms-biuras' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, From dbd3cebcc9feb4e0518fa0b24f210a56b6b8fcc7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 30 Dec 2023 20:21:21 +0100 Subject: [PATCH 045/180] Leverage ReflectionFunction::isAnonymous() --- Console/Descriptor/JsonDescriptor.php | 2 +- Console/Descriptor/MarkdownDescriptor.php | 2 +- Console/Descriptor/TextDescriptor.php | 2 +- Console/Descriptor/XmlDescriptor.php | 2 +- Kernel/MicroKernelTrait.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Console/Descriptor/JsonDescriptor.php b/Console/Descriptor/JsonDescriptor.php index f3c70310e..9562dc500 100644 --- a/Console/Descriptor/JsonDescriptor.php +++ b/Console/Descriptor/JsonDescriptor.php @@ -393,7 +393,7 @@ private function getCallableData(mixed $callable): array $data['type'] = 'closure'; $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if ($r->isAnonymous()) { return $data; } $data['name'] = $r->name; diff --git a/Console/Descriptor/MarkdownDescriptor.php b/Console/Descriptor/MarkdownDescriptor.php index 3b66c79cf..924951b5d 100644 --- a/Console/Descriptor/MarkdownDescriptor.php +++ b/Console/Descriptor/MarkdownDescriptor.php @@ -403,7 +403,7 @@ protected function describeCallable(mixed $callable, array $options = []): void $string .= "\n- Type: `closure`"; $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if ($r->isAnonymous()) { $this->write($string."\n"); return; diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index d13d3e13c..4e243c45e 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -649,7 +649,7 @@ private function formatCallable(mixed $callable): string if ($callable instanceof \Closure) { $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if ($r->isAnonymous()) { return 'Closure()'; } if ($class = $r->getClosureCalledClass()) { diff --git a/Console/Descriptor/XmlDescriptor.php b/Console/Descriptor/XmlDescriptor.php index d530936d7..14435f9e0 100644 --- a/Console/Descriptor/XmlDescriptor.php +++ b/Console/Descriptor/XmlDescriptor.php @@ -581,7 +581,7 @@ private function getCallableDocument(mixed $callable): \DOMDocument $callableXML->setAttribute('type', 'closure'); $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if ($r->isAnonymous()) { return $dom; } $callableXML->setAttribute('name', $r->name); diff --git a/Kernel/MicroKernelTrait.php b/Kernel/MicroKernelTrait.php index 73a7f6fe7..b3f49c059 100644 --- a/Kernel/MicroKernelTrait.php +++ b/Kernel/MicroKernelTrait.php @@ -214,7 +214,7 @@ public function loadRoutes(LoaderInterface $loader): RouteCollection if (\is_array($controller) && [0, 1] === array_keys($controller) && $this === $controller[0]) { $route->setDefault('_controller', ['kernel', $controller[1]]); - } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !str_contains($r->name, '{closure}')) { + } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !$r->isAnonymous()) { $route->setDefault('_controller', ['kernel', $r->name]); } } From 832108167271ee0c82413c14549f3a6a119ab6cc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 20 Dec 2023 08:12:55 +0100 Subject: [PATCH 046/180] mark classes implementing the WarmableInterface as final --- CHANGELOG.md | 1 + CacheWarmer/ConfigBuilderCacheWarmer.php | 2 ++ CacheWarmer/SerializerCacheWarmer.php | 2 ++ CacheWarmer/TranslationsCacheWarmer.php | 2 ++ CacheWarmer/ValidatorCacheWarmer.php | 2 ++ Routing/Router.php | 2 ++ Tests/Translation/TranslatorTest.php | 18 ------------------ Translation/Translator.php | 2 ++ 8 files changed, 13 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed156fda3..804b949dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.1 --- + * Mark classes `ConfigBuilderCacheWarmer`, `Router`, `SerializerCacheWarmer`, `TranslationsCacheWarmer`, `Translator` and `ValidatorCacheWarmer` as `final` * Move the Router `cache_dir` to `kernel.build_dir` * Deprecate the `router.cache_dir` config option * Add `rate_limiter` tags to rate limiter services diff --git a/CacheWarmer/ConfigBuilderCacheWarmer.php b/CacheWarmer/ConfigBuilderCacheWarmer.php index 04ba80f6a..6c93797c7 100644 --- a/CacheWarmer/ConfigBuilderCacheWarmer.php +++ b/CacheWarmer/ConfigBuilderCacheWarmer.php @@ -25,6 +25,8 @@ * Generate all config builders. * * @author Tobias Nyholm + * + * @final since Symfony 7.1 */ class ConfigBuilderCacheWarmer implements CacheWarmerInterface { diff --git a/CacheWarmer/SerializerCacheWarmer.php b/CacheWarmer/SerializerCacheWarmer.php index b1300516b..662c2136d 100644 --- a/CacheWarmer/SerializerCacheWarmer.php +++ b/CacheWarmer/SerializerCacheWarmer.php @@ -23,6 +23,8 @@ * Warms up XML and YAML serializer metadata. * * @author Titouan Galopin + * + * @final since Symfony 7.1 */ class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer { diff --git a/CacheWarmer/TranslationsCacheWarmer.php b/CacheWarmer/TranslationsCacheWarmer.php index 59a7865a1..37fa98aa7 100644 --- a/CacheWarmer/TranslationsCacheWarmer.php +++ b/CacheWarmer/TranslationsCacheWarmer.php @@ -21,6 +21,8 @@ * Generates the catalogues for translations. * * @author Xavier Leune + * + * @final since Symfony 7.1 */ class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { diff --git a/CacheWarmer/ValidatorCacheWarmer.php b/CacheWarmer/ValidatorCacheWarmer.php index d88fd36c8..3d9349a5b 100644 --- a/CacheWarmer/ValidatorCacheWarmer.php +++ b/CacheWarmer/ValidatorCacheWarmer.php @@ -24,6 +24,8 @@ * Warms up XML and YAML validator metadata. * * @author Titouan Galopin + * + * @final since Symfony 7.1 */ class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer { diff --git a/Routing/Router.php b/Routing/Router.php index b5b7567de..6712817eb 100644 --- a/Routing/Router.php +++ b/Routing/Router.php @@ -30,6 +30,8 @@ * This Router creates the Loader only when the cache is empty. * * @author Fabien Potencier + * + * @final since Symfony 7.1 */ class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface { diff --git a/Tests/Translation/TranslatorTest.php b/Tests/Translation/TranslatorTest.php index 2ef550ef0..1c8efd9b1 100644 --- a/Tests/Translation/TranslatorTest.php +++ b/Tests/Translation/TranslatorTest.php @@ -100,16 +100,6 @@ public function testTransWithCaching() $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax')); } - public function testTransWithCachingWithInvalidLocale() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid "invalid locale" locale.'); - $loader = $this->createMock(LoaderInterface::class); - $translator = $this->getTranslator($loader, ['cache_dir' => $this->tmpDir], 'loader', TranslatorWithInvalidLocale::class); - - $translator->trans('foo'); - } - public function testLoadResourcesWithoutCaching() { $loader = new YamlFileLoader(); @@ -418,11 +408,3 @@ private function createTranslator($loader, $options, $translatorClass = Translat ); } } - -class TranslatorWithInvalidLocale extends Translator -{ - public function getLocale(): string - { - return 'invalid locale'; - } -} diff --git a/Translation/Translator.php b/Translation/Translator.php index 644b0caac..91a070923 100644 --- a/Translation/Translator.php +++ b/Translation/Translator.php @@ -21,6 +21,8 @@ /** * @author Fabien Potencier + * + * @final since Symfony 7.1 */ class Translator extends BaseTranslator implements WarmableInterface { From fa06aec731adeefe9d4bd253b179fb27ad569b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Tue, 19 Dec 2023 13:47:41 +0100 Subject: [PATCH 047/180] [FrameworkBundle] Prevent silenced warning by checking if file exists --- Command/CacheClearCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Command/CacheClearCommand.php b/Command/CacheClearCommand.php index 878157e87..d8f23f7de 100644 --- a/Command/CacheClearCommand.php +++ b/Command/CacheClearCommand.php @@ -200,7 +200,7 @@ private function isNfs(string $dir): bool if (null === $mounts) { $mounts = []; - if ('/' === \DIRECTORY_SEPARATOR && $files = @file('/proc/mounts')) { + if ('/' === \DIRECTORY_SEPARATOR && is_readable('/proc/mounts') && $files = @file('/proc/mounts')) { foreach ($files as $mount) { $mount = \array_slice(explode(' ', $mount), 1, -3); if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) { From ab37429c57a88caf8f1b9846934b439fb26d782d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 31 Dec 2023 11:32:07 +0100 Subject: [PATCH 048/180] add a private_ranges shortcut for trusted_proxies --- CHANGELOG.md | 1 + DependencyInjection/Configuration.php | 8 +++++++- .../Fixtures/php/trusted_proxies_private_ranges.php | 5 +++++ .../Fixtures/xml/trusted_proxies_private_ranges.xml | 9 +++++++++ .../Fixtures/yml/trusted_proxies_private_ranges.yml | 2 ++ Tests/DependencyInjection/FrameworkExtensionTestCase.php | 8 ++++++++ 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 Tests/DependencyInjection/Fixtures/php/trusted_proxies_private_ranges.php create mode 100644 Tests/DependencyInjection/Fixtures/xml/trusted_proxies_private_ranges.xml create mode 100644 Tests/DependencyInjection/Fixtures/yml/trusted_proxies_private_ranges.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 804b949dc..43d7f6295 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.1 --- + * Add `private_ranges` as a shortcut for private IP address ranges to the `trusted_proxies` option * Mark classes `ConfigBuilderCacheWarmer`, `Router`, `SerializerCacheWarmer`, `TranslationsCacheWarmer`, `Translator` and `ValidatorCacheWarmer` as `final` * Move the Router `cache_dir` to `kernel.build_dir` * Deprecate the `router.cache_dir` config option diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 31dbc6f8d..7247cbe5d 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -29,6 +29,7 @@ use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\Lock\Lock; use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\Mailer\Mailer; @@ -111,7 +112,12 @@ public function getConfigTreeBuilder(): TreeBuilder ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() ->prototype('scalar')->end() ->end() - ->scalarNode('trusted_proxies')->end() + ->scalarNode('trusted_proxies') + ->beforeNormalization() + ->ifTrue(fn ($v) => 'private_ranges' === $v) + ->then(fn ($v) => implode(',', IpUtils::PRIVATE_SUBNETS)) + ->end() + ->end() ->arrayNode('trusted_headers') ->fixXmlConfig('trusted_header') ->performNoDeepMerging() diff --git a/Tests/DependencyInjection/Fixtures/php/trusted_proxies_private_ranges.php b/Tests/DependencyInjection/Fixtures/php/trusted_proxies_private_ranges.php new file mode 100644 index 000000000..e3a5dc4a5 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/php/trusted_proxies_private_ranges.php @@ -0,0 +1,5 @@ +loadFromExtension('framework', [ + 'trusted_proxies' => 'private_ranges', +]); diff --git a/Tests/DependencyInjection/Fixtures/xml/trusted_proxies_private_ranges.xml b/Tests/DependencyInjection/Fixtures/xml/trusted_proxies_private_ranges.xml new file mode 100644 index 000000000..700f84959 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/xml/trusted_proxies_private_ranges.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/Tests/DependencyInjection/Fixtures/yml/trusted_proxies_private_ranges.yml b/Tests/DependencyInjection/Fixtures/yml/trusted_proxies_private_ranges.yml new file mode 100644 index 000000000..b98bb2f78 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/yml/trusted_proxies_private_ranges.yml @@ -0,0 +1,2 @@ +framework: + trusted_proxies: private_ranges diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 4bd3c481f..0d97dcf62 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -52,6 +52,7 @@ use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\RetryableHttpClient; use Symfony\Component\HttpClient\ScopingHttpClient; +use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; @@ -2265,6 +2266,13 @@ public function testNotifierWithSpecificMessageBus() $this->assertEquals(new Reference('app.another_bus'), $container->getDefinition('notifier.channel.sms')->getArgument(1)); } + public function testTrustedProxiesWithPrivateRanges() + { + $container = $this->createContainerFromFile('trusted_proxies_private_ranges'); + + $this->assertSame(IpUtils::PRIVATE_SUBNETS, array_map('trim', explode(',', $container->getParameter('kernel.trusted_proxies')))); + } + public function testWebhook() { if (!class_exists(WebhookController::class)) { From d4819b6ae802baca579f16283dfc387ab8068212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rokas=20Mikalk=C4=97nas?= Date: Sun, 31 Dec 2023 07:14:05 +0200 Subject: [PATCH 049/180] [Messenger] Add jitter parameter to MultiplierRetryStrategy --- DependencyInjection/Configuration.php | 1 + DependencyInjection/FrameworkExtension.php | 3 ++- Resources/config/messenger.php | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 7247cbe5d..702b4f610 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1592,6 +1592,7 @@ function ($a) { ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))')->end() ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() + ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness to apply to the delay (between 0 and 1)')->end() ->end() ->end() ->scalarNode('rate_limiter') diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 4750729ef..2b2412bae 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2195,7 +2195,8 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder ->replaceArgument(0, $transport['retry_strategy']['max_retries']) ->replaceArgument(1, $transport['retry_strategy']['delay']) ->replaceArgument(2, $transport['retry_strategy']['multiplier']) - ->replaceArgument(3, $transport['retry_strategy']['max_delay']); + ->replaceArgument(3, $transport['retry_strategy']['max_delay']) + ->replaceArgument(4, $transport['retry_strategy']['jitter']); $container->setDefinition($retryServiceId, $retryDefinition); $transportRetryReferences[$name] = new Reference($retryServiceId); diff --git a/Resources/config/messenger.php b/Resources/config/messenger.php index 556affd07..f71fcf344 100644 --- a/Resources/config/messenger.php +++ b/Resources/config/messenger.php @@ -160,6 +160,7 @@ abstract_arg('delay ms'), abstract_arg('multiplier'), abstract_arg('max delay ms'), + abstract_arg('jitter'), ]) // rate limiter From 958ec0b7cee12cd49a9168b853a6fe7e3811c194 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 6 Jan 2024 17:00:23 +0100 Subject: [PATCH 050/180] add the new jitter option to the XML schema definition --- Resources/config/schema/symfony-1.0.xsd | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index 57cc92334..9279eaf68 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -609,6 +609,7 @@ + From c866a3f1550525adf3271122865cf5d76d2d988f Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 11 Oct 2023 17:07:16 +0200 Subject: [PATCH 051/180] [FrameworkBundle][RemoteEvent][Routing][Scheduler] Add PHPDoc to attributes properties --- Routing/Attribute/AsRoutingConditionService.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Routing/Attribute/AsRoutingConditionService.php b/Routing/Attribute/AsRoutingConditionService.php index d1f1a5f34..2bc407978 100644 --- a/Routing/Attribute/AsRoutingConditionService.php +++ b/Routing/Attribute/AsRoutingConditionService.php @@ -41,6 +41,10 @@ #[\Attribute(\Attribute::TARGET_CLASS)] class AsRoutingConditionService extends AutoconfigureTag { + /** + * @param string|null $alias The alias of the service to use it in routing condition expressions + * @param int $priority Defines a priority that allows the routing condition service to override a service with the same alias + */ public function __construct( string $alias = null, int $priority = 0, From a4fbe7b7c15d48d409e2cd522e223dc989a76f35 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 10 Jan 2024 12:28:47 +0100 Subject: [PATCH 052/180] do not mock the RequestStack class --- Tests/Console/ApplicationTest.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Tests/Console/ApplicationTest.php b/Tests/Console/ApplicationTest.php index 4411d59ba..42691c75b 100644 --- a/Tests/Console/ApplicationTest.php +++ b/Tests/Console/ApplicationTest.php @@ -243,11 +243,6 @@ private function getKernel(array $bundles, $useDispatcher = false) { $container = $this->createMock(ContainerInterface::class); - $requestStack = $this->createMock(RequestStack::class); - $requestStack->expects($this->any()) - ->method('push') - ; - if ($useDispatcher) { $dispatcher = $this->createMock(EventDispatcherInterface::class); $dispatcher @@ -258,7 +253,7 @@ private function getKernel(array $bundles, $useDispatcher = false) $container->expects($this->atLeastOnce()) ->method('get') ->willReturnMap([ - ['.virtual_request_stack', 2, $requestStack], + ['.virtual_request_stack', 2, new RequestStack()], ['event_dispatcher', 1, $dispatcher], ]) ; From e95e5b8b13f85998f550a1131c2989358a272f6a Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Wed, 4 Oct 2023 08:57:42 +0200 Subject: [PATCH 053/180] [TypeInfo] Introduce component Co-authored-by: Baptiste Leduc --- DependencyInjection/Configuration.php | 14 ++++++ DependencyInjection/FrameworkExtension.php | 26 ++++++++++ Resources/config/schema/symfony-1.0.xsd | 5 ++ Resources/config/type_info.php | 50 +++++++++++++++++++ .../DependencyInjection/ConfigurationTest.php | 4 ++ .../DependencyInjection/Fixtures/php/full.php | 1 + .../Fixtures/php/type_info.php | 11 ++++ .../DependencyInjection/Fixtures/xml/full.xml | 1 + .../Fixtures/xml/type_info.xml | 13 +++++ .../DependencyInjection/Fixtures/yml/full.yml | 1 + .../Fixtures/yml/type_info.yml | 8 +++ .../FrameworkExtensionTestCase.php | 6 +++ Tests/Functional/TypeInfoTest.php | 32 ++++++++++++ Tests/Functional/app/TypeInfo/Dummy.php | 21 ++++++++ Tests/Functional/app/TypeInfo/bundles.php | 18 +++++++ Tests/Functional/app/TypeInfo/config.yml | 11 ++++ composer.json | 1 + 17 files changed, 223 insertions(+) create mode 100644 Resources/config/type_info.php create mode 100644 Tests/DependencyInjection/Fixtures/php/type_info.php create mode 100644 Tests/DependencyInjection/Fixtures/xml/type_info.xml create mode 100644 Tests/DependencyInjection/Fixtures/yml/type_info.yml create mode 100644 Tests/Functional/TypeInfoTest.php create mode 100644 Tests/Functional/app/TypeInfo/Dummy.php create mode 100644 Tests/Functional/app/TypeInfo/bundles.php create mode 100644 Tests/Functional/app/TypeInfo/config.yml diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 702b4f610..81ee3e06e 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -44,6 +44,7 @@ use Symfony\Component\Serializer\Encoder\JsonDecode; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Translation\Translator; +use Symfony\Component\TypeInfo\Type; use Symfony\Component\Uid\Factory\UuidFactory; use Symfony\Component\Validator\Validation; use Symfony\Component\Webhook\Controller\WebhookController; @@ -164,6 +165,7 @@ public function getConfigTreeBuilder(): TreeBuilder $this->addAnnotationsSection($rootNode); $this->addSerializerSection($rootNode, $enableIfStandalone); $this->addPropertyAccessSection($rootNode, $willBeAvailable); + $this->addTypeInfoSection($rootNode, $enableIfStandalone); $this->addPropertyInfoSection($rootNode, $enableIfStandalone); $this->addCacheSection($rootNode, $willBeAvailable); $this->addPhpErrorsSection($rootNode); @@ -1162,6 +1164,18 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable ; } + private function addTypeInfoSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void + { + $rootNode + ->children() + ->arrayNode('type_info') + ->info('Type info configuration') + ->{$enableIfStandalone('symfony/type-info', Type::class)}() + ->end() + ->end() + ; + } + private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void { $rootNode diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 9c9446fb0..933c141e1 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -53,6 +53,7 @@ use Symfony\Component\Console\Debug\CliRequest; use Symfony\Component\Console\Messenger\RunCommandMessageHandler; use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -167,6 +168,8 @@ use Symfony\Component\Translation\LocaleSwitcher; use Symfony\Component\Translation\PseudoLocalizationTranslator; use Symfony\Component\Translation\Translator; +use Symfony\Component\TypeInfo\Type; +use Symfony\Component\TypeInfo\TypeResolver\StringTypeResolver; use Symfony\Component\Uid\Factory\UuidFactory; use Symfony\Component\Uid\UuidV4; use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider; @@ -388,6 +391,10 @@ public function load(array $configs, ContainerBuilder $container): void $container->removeDefinition('console.command.serializer_debug'); } + if ($this->readConfigEnabled('type_info', $container, $config['type_info'])) { + $this->registerTypeInfoConfiguration($container, $loader); + } + if ($propertyInfoEnabled) { $this->registerPropertyInfoConfiguration($container, $loader); } @@ -1953,6 +1960,25 @@ private function registerPropertyInfoConfiguration(ContainerBuilder $container, } } + private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void + { + if (!class_exists(Type::class)) { + throw new LogicException('TypeInfo support cannot be enabled as the TypeInfo component is not installed. Try running "composer require symfony/type-info".'); + } + + $loader->load('type_info.php'); + + if (ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/type-info'])) { + $container->register('type_info.resolver.string', StringTypeResolver::class); + + /** @var ServiceLocatorArgument $resolversLocator */ + $resolversLocator = $container->getDefinition('type_info.resolver')->getArgument(0); + $resolversLocator->setValues($resolversLocator->getValues() + [ + 'string' => new Reference('type_info.resolver.string'), + ]); + } + } + private function registerLockConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void { $loader->load('lock.php'); diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index 9279eaf68..6ebcfedbf 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -27,6 +27,7 @@ + @@ -327,6 +328,10 @@ + + + + diff --git a/Resources/config/type_info.php b/Resources/config/type_info.php new file mode 100644 index 000000000..71e3646a1 --- /dev/null +++ b/Resources/config/type_info.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\TypeInfo\TypeContext\TypeContextFactory; +use Symfony\Component\TypeInfo\TypeResolver\ReflectionParameterTypeResolver; +use Symfony\Component\TypeInfo\TypeResolver\ReflectionPropertyTypeResolver; +use Symfony\Component\TypeInfo\TypeResolver\ReflectionReturnTypeResolver; +use Symfony\Component\TypeInfo\TypeResolver\ReflectionTypeResolver; +use Symfony\Component\TypeInfo\TypeResolver\TypeResolver; +use Symfony\Component\TypeInfo\TypeResolver\TypeResolverInterface; + +return static function (ContainerConfigurator $container) { + $container->services() + // type context + ->set('type_info.type_context_factory', TypeContextFactory::class) + ->args([service('type_info.resolver.string')->nullOnInvalid()]) + + // type resolvers + ->set('type_info.resolver', TypeResolver::class) + ->args([service_locator([ + \ReflectionType::class => service('type_info.resolver.reflection_type'), + \ReflectionParameter::class => service('type_info.resolver.reflection_parameter'), + \ReflectionProperty::class => service('type_info.resolver.reflection_property'), + \ReflectionFunctionAbstract::class => service('type_info.resolver.reflection_return'), + ])]) + ->alias(TypeResolverInterface::class, 'type_info.resolver') + + ->set('type_info.resolver.reflection_type', ReflectionTypeResolver::class) + ->args([service('type_info.type_context_factory')]) + + ->set('type_info.resolver.reflection_parameter', ReflectionParameterTypeResolver::class) + ->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')]) + + ->set('type_info.resolver.reflection_property', ReflectionPropertyTypeResolver::class) + ->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')]) + + ->set('type_info.resolver.reflection_return', ReflectionReturnTypeResolver::class) + ->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')]) + ; +}; diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index d56cfa90d..5a4005bbf 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -28,6 +28,7 @@ use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter; use Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory; use Symfony\Component\Serializer\Encoder\JsonDecode; +use Symfony\Component\TypeInfo\Type; use Symfony\Component\Uid\Factory\UuidFactory; class ConfigurationTest extends TestCase @@ -624,6 +625,9 @@ protected static function getBundleDefaultConfig() 'throw_exception_on_invalid_index' => false, 'throw_exception_on_invalid_property_path' => true, ], + 'type_info' => [ + 'enabled' => !class_exists(FullStack::class) && class_exists(Type::class), + ], 'property_info' => [ 'enabled' => !class_exists(FullStack::class), ], diff --git a/Tests/DependencyInjection/Fixtures/php/full.php b/Tests/DependencyInjection/Fixtures/php/full.php index b5d8061e4..4fbf72a9f 100644 --- a/Tests/DependencyInjection/Fixtures/php/full.php +++ b/Tests/DependencyInjection/Fixtures/php/full.php @@ -70,6 +70,7 @@ 'default_context' => ['enable_max_depth' => true], ], 'property_info' => true, + 'type_info' => true, 'ide' => 'file%%link%%format', 'request' => [ 'formats' => [ diff --git a/Tests/DependencyInjection/Fixtures/php/type_info.php b/Tests/DependencyInjection/Fixtures/php/type_info.php new file mode 100644 index 000000000..0e7dcbae0 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/php/type_info.php @@ -0,0 +1,11 @@ +loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'type_info' => [ + 'enabled' => true, + ], +]); diff --git a/Tests/DependencyInjection/Fixtures/xml/full.xml b/Tests/DependencyInjection/Fixtures/xml/full.xml index 92e4405a0..fd5d52e1c 100644 --- a/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -40,5 +40,6 @@ + diff --git a/Tests/DependencyInjection/Fixtures/xml/type_info.xml b/Tests/DependencyInjection/Fixtures/xml/type_info.xml new file mode 100644 index 000000000..0fe4d525d --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/xml/type_info.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/Tests/DependencyInjection/Fixtures/yml/full.yml b/Tests/DependencyInjection/Fixtures/yml/full.yml index 883e9d6c2..96001f1d2 100644 --- a/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -59,6 +59,7 @@ framework: max_depth_handler: my.max.depth.handler default_context: enable_max_depth: true + type_info: ~ property_info: ~ ide: file%%link%%format request: diff --git a/Tests/DependencyInjection/Fixtures/yml/type_info.yml b/Tests/DependencyInjection/Fixtures/yml/type_info.yml new file mode 100644 index 000000000..4d6b405b2 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/yml/type_info.yml @@ -0,0 +1,8 @@ +framework: + annotations: false + http_method_override: false + handle_all_throwables: true + php_errors: + log: true + type_info: + enabled: true diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 0d97dcf62..8c4711c64 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1616,6 +1616,12 @@ public function testSerializerServiceIsNotRegisteredWhenDisabled() $this->assertFalse($container->hasDefinition('serializer')); } + public function testTypeInfoEnabled() + { + $container = $this->createContainerFromFile('type_info'); + $this->assertTrue($container->has('type_info.resolver')); + } + public function testPropertyInfoEnabled() { $container = $this->createContainerFromFile('property_info'); diff --git a/Tests/Functional/TypeInfoTest.php b/Tests/Functional/TypeInfoTest.php new file mode 100644 index 000000000..6acdb9c81 --- /dev/null +++ b/Tests/Functional/TypeInfoTest.php @@ -0,0 +1,32 @@ + + * + * 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 PHPStan\PhpDocParser\Parser\PhpDocParser; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\TypeInfo\Dummy; +use Symfony\Component\TypeInfo\Type; + +class TypeInfoTest extends AbstractWebTestCase +{ + public function testComponent() + { + static::bootKernel(['test_case' => 'TypeInfo']); + + $this->assertEquals(Type::string(), static::getContainer()->get('type_info.resolver')->resolve(new \ReflectionProperty(Dummy::class, 'name'))); + + if (!class_exists(PhpDocParser::class)) { + $this->markTestSkipped('"phpstan/phpdoc-parser" dependency is required.'); + } + + $this->assertEquals(Type::int(), static::getContainer()->get('type_info.resolver')->resolve('int')); + } +} diff --git a/Tests/Functional/app/TypeInfo/Dummy.php b/Tests/Functional/app/TypeInfo/Dummy.php new file mode 100644 index 000000000..0f517df51 --- /dev/null +++ b/Tests/Functional/app/TypeInfo/Dummy.php @@ -0,0 +1,21 @@ + + * + * 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\app\TypeInfo; + +/** + * @author Mathias Arlaud + * @author Baptiste Leduc + */ +class Dummy +{ + public string $name; +} diff --git a/Tests/Functional/app/TypeInfo/bundles.php b/Tests/Functional/app/TypeInfo/bundles.php new file mode 100644 index 000000000..15ff182c6 --- /dev/null +++ b/Tests/Functional/app/TypeInfo/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/TypeInfo/config.yml b/Tests/Functional/app/TypeInfo/config.yml new file mode 100644 index 000000000..35c7bb4c4 --- /dev/null +++ b/Tests/Functional/app/TypeInfo/config.yml @@ -0,0 +1,11 @@ +imports: + - { resource: ../config/default.yml } + +framework: + http_method_override: false + type_info: true + +services: + type_info.resolver.alias: + alias: type_info.resolver + public: true diff --git a/composer.json b/composer.json index 9a50605a2..766bc8064 100644 --- a/composer.json +++ b/composer.json @@ -64,6 +64,7 @@ "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", "symfony/twig-bundle": "^6.4|^7.0", + "symfony/type-info": "^7.1", "symfony/validator": "^6.4|^7.0", "symfony/workflow": "^6.4|^7.0", "symfony/yaml": "^6.4|^7.0", From f26cb41a1eaffbe43105157f172fe92c54212f2a Mon Sep 17 00:00:00 2001 From: Mathieu Santostefano Date: Tue, 16 Jan 2024 15:06:57 +0100 Subject: [PATCH 054/180] Add Resend Mailer bridge --- DependencyInjection/FrameworkExtension.php | 2 ++ Resources/config/mailer_transports.php | 2 ++ Resources/config/mailer_webhook.php | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 9c9446fb0..cf8bb8dfc 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2572,6 +2572,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', + 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', @@ -2591,6 +2592,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Mailgun\Webhook\MailgunRequestParser::class => 'mailer.webhook.request_parser.mailgun', MailerBridge\Mailjet\Webhook\MailjetRequestParser::class => 'mailer.webhook.request_parser.mailjet', MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark', + MailerBridge\Resend\Webhook\ResendRequestParser::class => 'mailer.webhook.request_parser.resend', MailerBridge\Sendgrid\Webhook\SendgridRequestParser::class => 'mailer.webhook.request_parser.sendgrid', ]; diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index f95fc6d64..5434b4c56 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -22,6 +22,7 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; +use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; @@ -55,6 +56,7 @@ 'native' => NativeTransportFactory::class, 'null' => NullTransportFactory::class, 'postmark' => PostmarkTransportFactory::class, + 'resend' => ResendTransportFactory::class, 'scaleway' => ScalewayTransportFactory::class, 'sendgrid' => SendgridTransportFactory::class, 'sendmail' => SendmailTransportFactory::class, diff --git a/Resources/config/mailer_webhook.php b/Resources/config/mailer_webhook.php index bb487b36c..5c1014713 100644 --- a/Resources/config/mailer_webhook.php +++ b/Resources/config/mailer_webhook.php @@ -19,6 +19,8 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Webhook\MailjetRequestParser; use Symfony\Component\Mailer\Bridge\Postmark\RemoteEvent\PostmarkPayloadConverter; use Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser; +use Symfony\Component\Mailer\Bridge\Resend\RemoteEvent\ResendPayloadConverter; +use Symfony\Component\Mailer\Bridge\Resend\Webhook\ResendRequestParser; use Symfony\Component\Mailer\Bridge\Sendgrid\RemoteEvent\SendgridPayloadConverter; use Symfony\Component\Mailer\Bridge\Sendgrid\Webhook\SendgridRequestParser; @@ -44,6 +46,11 @@ ->args([service('mailer.payload_converter.postmark')]) ->alias(PostmarkRequestParser::class, 'mailer.webhook.request_parser.postmark') + ->set('mailer.payload_converter.resend', ResendPayloadConverter::class) + ->set('mailer.webhook.request_parser.resend', ResendRequestParser::class) + ->args([service('mailer.payload_converter.resend')]) + ->alias(ResendRequestParser::class, 'mailer.webhook.request_parser.resend') + ->set('mailer.payload_converter.sendgrid', SendgridPayloadConverter::class) ->set('mailer.webhook.request_parser.sendgrid', SendgridRequestParser::class) ->args([service('mailer.payload_converter.sendgrid')]) From 2ce6f817c4fc7cba537cbd80d8a3992558c13b2d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 9 Jan 2024 15:08:59 +0100 Subject: [PATCH 055/180] do not mock the ContainerInterface --- Tests/CacheWarmer/RouterCacheWarmerTest.php | 26 +++++------ Tests/Command/CachePoolClearCommandTest.php | 6 +-- Tests/Command/CachePoolDeleteCommandTest.php | 6 +-- Tests/Command/CachePruneCommandTest.php | 6 +-- Tests/Command/RouterMatchCommandTest.php | 17 +------ Tests/Console/ApplicationTest.php | 47 +++---------------- Tests/Controller/ControllerResolverTest.php | 8 +--- Tests/Routing/RouterTest.php | 48 +++++++------------- Tests/Translation/TranslatorTest.php | 17 +++---- 9 files changed, 51 insertions(+), 130 deletions(-) diff --git a/Tests/CacheWarmer/RouterCacheWarmerTest.php b/Tests/CacheWarmer/RouterCacheWarmerTest.php index 7686b139f..615010a47 100644 --- a/Tests/CacheWarmer/RouterCacheWarmerTest.php +++ b/Tests/CacheWarmer/RouterCacheWarmerTest.php @@ -12,8 +12,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Component\Routing\RouterInterface; @@ -21,11 +21,11 @@ class RouterCacheWarmerTest extends TestCase { public function testWarmUpWithWarmableInterfaceWithBuildDir() { - $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); + $container = new Container(); $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); - $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); - $routerCacheWarmer = new RouterCacheWarmer($containerMock); + $container->set('router', $routerMock); + $routerCacheWarmer = new RouterCacheWarmer($container); $routerCacheWarmer->warmUp('/tmp/cache', '/tmp/build'); $routerMock->expects($this->any())->method('warmUp')->with('/tmp/cache', '/tmp/build')->willReturn([]); @@ -34,11 +34,11 @@ public function testWarmUpWithWarmableInterfaceWithBuildDir() public function testWarmUpWithoutWarmableInterfaceWithBuildDir() { - $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); + $container = new Container(); $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); - $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); - $routerCacheWarmer = new RouterCacheWarmer($containerMock); + $container->set('router', $routerMock); + $routerCacheWarmer = new RouterCacheWarmer($container); $this->expectException(\LogicException::class); $this->expectExceptionMessage('cannot be warmed up because it does not implement "Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface"'); $routerCacheWarmer->warmUp('/tmp/cache', '/tmp/build'); @@ -46,11 +46,11 @@ public function testWarmUpWithoutWarmableInterfaceWithBuildDir() public function testWarmUpWithWarmableInterfaceWithoutBuildDir() { - $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); + $container = new Container(); $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); - $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); - $routerCacheWarmer = new RouterCacheWarmer($containerMock); + $container->set('router', $routerMock); + $routerCacheWarmer = new RouterCacheWarmer($container); $preload = $routerCacheWarmer->warmUp('/tmp'); $routerMock->expects($this->never())->method('warmUp'); @@ -60,11 +60,11 @@ public function testWarmUpWithWarmableInterfaceWithoutBuildDir() public function testWarmUpWithoutWarmableInterfaceWithoutBuildDir() { - $containerMock = $this->getMockBuilder(ContainerInterface::class)->onlyMethods(['get', 'has'])->getMock(); + $container = new Container(); $routerMock = $this->getMockBuilder(testRouterInterfaceWithoutWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection'])->getMock(); - $containerMock->expects($this->any())->method('get')->with('router')->willReturn($routerMock); - $routerCacheWarmer = new RouterCacheWarmer($containerMock); + $container->set('router', $routerMock); + $routerCacheWarmer = new RouterCacheWarmer($container); $preload = $routerCacheWarmer->warmUp('/tmp'); self::assertSame([], $preload); } diff --git a/Tests/Command/CachePoolClearCommandTest.php b/Tests/Command/CachePoolClearCommandTest.php index fb7358831..3a927f217 100644 --- a/Tests/Command/CachePoolClearCommandTest.php +++ b/Tests/Command/CachePoolClearCommandTest.php @@ -17,7 +17,7 @@ use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\Console\Tester\CommandCompletionTester; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; use Symfony\Component\HttpKernel\KernelInterface; @@ -54,13 +54,11 @@ public static function provideCompletionSuggestions(): iterable private function getKernel(): MockObject&KernelInterface { - $container = $this->createMock(ContainerInterface::class); - $kernel = $this->createMock(KernelInterface::class); $kernel ->expects($this->any()) ->method('getContainer') - ->willReturn($container); + ->willReturn(new Container()); $kernel ->expects($this->once()) diff --git a/Tests/Command/CachePoolDeleteCommandTest.php b/Tests/Command/CachePoolDeleteCommandTest.php index caa7eb550..3db39e121 100644 --- a/Tests/Command/CachePoolDeleteCommandTest.php +++ b/Tests/Command/CachePoolDeleteCommandTest.php @@ -18,7 +18,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; use Symfony\Component\HttpKernel\KernelInterface; @@ -108,13 +108,11 @@ public static function provideCompletionSuggestions(): iterable private function getKernel(): MockObject&KernelInterface { - $container = $this->createMock(ContainerInterface::class); - $kernel = $this->createMock(KernelInterface::class); $kernel ->expects($this->any()) ->method('getContainer') - ->willReturn($container); + ->willReturn(new Container()); $kernel ->expects($this->once()) diff --git a/Tests/Command/CachePruneCommandTest.php b/Tests/Command/CachePruneCommandTest.php index 54467f1ef..a2d0ad7fe 100644 --- a/Tests/Command/CachePruneCommandTest.php +++ b/Tests/Command/CachePruneCommandTest.php @@ -18,7 +18,7 @@ use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpKernel\KernelInterface; class CachePruneCommandTest extends TestCase @@ -50,13 +50,11 @@ private function getEmptyRewindableGenerator(): RewindableGenerator private function getKernel(): MockObject&KernelInterface { - $container = $this->createMock(ContainerInterface::class); - $kernel = $this->createMock(KernelInterface::class); $kernel ->expects($this->any()) ->method('getContainer') - ->willReturn($container); + ->willReturn(new Container()); $kernel ->expects($this->once()) diff --git a/Tests/Command/RouterMatchCommandTest.php b/Tests/Command/RouterMatchCommandTest.php index 7dab41991..b6b6771f9 100644 --- a/Tests/Command/RouterMatchCommandTest.php +++ b/Tests/Command/RouterMatchCommandTest.php @@ -16,7 +16,7 @@ use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; @@ -72,24 +72,11 @@ private function getRouter() private function getKernel() { - $container = $this->createMock(ContainerInterface::class); - $container - ->expects($this->atLeastOnce()) - ->method('has') - ->willReturnCallback(fn ($id) => 'console.command_loader' !== $id) - ; - $container - ->expects($this->any()) - ->method('get') - ->with('router') - ->willReturn($this->getRouter()) - ; - $kernel = $this->createMock(KernelInterface::class); $kernel ->expects($this->any()) ->method('getContainer') - ->willReturn($container) + ->willReturn(new Container()) ; $kernel ->expects($this->once()) diff --git a/Tests/Console/ApplicationTest.php b/Tests/Console/ApplicationTest.php index 42691c75b..9afb5a2fd 100644 --- a/Tests/Console/ApplicationTest.php +++ b/Tests/Console/ApplicationTest.php @@ -22,11 +22,11 @@ use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\ApplicationTester; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\KernelInterface; @@ -241,7 +241,10 @@ private function createEventForSuggestingPackages(string $command, array $altern private function getKernel(array $bundles, $useDispatcher = false) { - $container = $this->createMock(ContainerInterface::class); + $container = new Container(new ParameterBag([ + 'console.command.ids' => [], + 'console.lazy_command.ids' => [], + ])); if ($useDispatcher) { $dispatcher = $this->createMock(EventDispatcherInterface::class); @@ -250,45 +253,9 @@ private function getKernel(array $bundles, $useDispatcher = false) ->method('dispatch') ; - $container->expects($this->atLeastOnce()) - ->method('get') - ->willReturnMap([ - ['.virtual_request_stack', 2, new RequestStack()], - ['event_dispatcher', 1, $dispatcher], - ]) - ; + $container->set('event_dispatcher', $dispatcher); } - $container - ->expects($this->exactly(2)) - ->method('hasParameter') - ->willReturnCallback(function (...$args) { - static $series = [ - ['console.command.ids'], - ['console.lazy_command.ids'], - ]; - - $this->assertSame(array_shift($series), $args); - - return true; - }) - ; - - $container - ->expects($this->exactly(2)) - ->method('getParameter') - ->willReturnCallback(function (...$args) { - static $series = [ - ['console.lazy_command.ids'], - ['console.command.ids'], - ]; - - $this->assertSame(array_shift($series), $args); - - return []; - }) - ; - $kernel = $this->createMock(KernelInterface::class); $kernel->expects($this->once())->method('boot'); $kernel diff --git a/Tests/Controller/ControllerResolverTest.php b/Tests/Controller/ControllerResolverTest.php index 0c51924a4..0c03dc460 100644 --- a/Tests/Controller/ControllerResolverTest.php +++ b/Tests/Controller/ControllerResolverTest.php @@ -16,7 +16,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest; @@ -107,7 +106,7 @@ class_exists(AbstractControllerTest::class); protected function createControllerResolver(LoggerInterface $logger = null, Psr11ContainerInterface $container = null) { if (!$container) { - $container = $this->createMockContainer(); + $container = new Container(); } return new ControllerResolver($container, $logger); @@ -117,11 +116,6 @@ protected function createMockParser() { return $this->createMock(ControllerNameParser::class); } - - protected function createMockContainer() - { - return $this->createMock(ContainerInterface::class); - } } class DummyController extends AbstractController diff --git a/Tests/Routing/RouterTest.php b/Tests/Routing/RouterTest.php index 3e185b54c..11c0dc7e6 100644 --- a/Tests/Routing/RouterTest.php +++ b/Tests/Routing/RouterTest.php @@ -23,6 +23,8 @@ use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\Routing\Loader\YamlFileLoader; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -406,7 +408,8 @@ public function testExceptionOnNonStringParameter() $routes->add('foo', new Route('/%object%')); $sc = $this->getPsr11ServiceContainer($routes); - $parameters = $this->getParameterBag(['object' => new \stdClass()]); + $parameters = new Container(); + $parameters->set('object', new \stdClass()); $router = new Router($sc, 'foo', [], null, $parameters); @@ -424,19 +427,15 @@ public function testExceptionOnNonStringParameterWithSfContainer() $sc = $this->getServiceContainer($routes); - $pc = $this->createMock(ContainerInterface::class); - $pc - ->expects($this->once()) - ->method('get') - ->willReturn(new \stdClass()) - ; + $pc = new Container(); + $pc->set('object', new \stdClass()); $router = new Router($sc, 'foo', [], null, $pc); $this->expectException(RuntimeException::class); $this->expectExceptionMessage('The container parameter "object", used in the route configuration value "/%object%", must be a string or numeric, but it is of type "stdClass".'); - $router->getRouteCollection()->get('foo'); + $router->getRouteCollection(); } /** @@ -483,7 +482,9 @@ public function testGetRouteCollectionAddsContainerParametersResource() $router = new Router($sc, 'foo', [], null, $parameters); - $router->getRouteCollection(); + $routeCollection = $router->getRouteCollection(); + + $this->assertEquals([new ContainerParametersResource(['locale' => 'en'])], $routeCollection->getResources()); } public function testGetRouteCollectionAddsContainerParametersResourceWithSfContainer() @@ -617,13 +618,8 @@ private function getServiceContainer(RouteCollection $routes): Container ->willReturn($routes) ; - $sc = $this->getMockBuilder(Container::class)->onlyMethods(['get'])->getMock(); - - $sc - ->expects($this->once()) - ->method('get') - ->willReturn($loader) - ; + $sc = new Container(); + $sc->set('routing.loader', $loader); return $sc; } @@ -638,26 +634,14 @@ private function getPsr11ServiceContainer(RouteCollection $routes): ContainerInt ->willReturn($routes) ; - $sc = $this->createMock(ContainerInterface::class); - - $sc - ->expects($this->once()) - ->method('get') - ->willReturn($loader) - ; + $container = new Container(); + $container->set('routing.loader', $loader); - return $sc; + return $container; } private function getParameterBag(array $params = []): ContainerInterface { - $bag = $this->createMock(ContainerInterface::class); - $bag - ->expects($this->any()) - ->method('get') - ->willReturnCallback(fn ($key) => $params[$key] ?? null) - ; - - return $bag; + return new ContainerBag(new Container(new ParameterBag($params))); } } diff --git a/Tests/Translation/TranslatorTest.php b/Tests/Translation/TranslatorTest.php index 1c8efd9b1..ff15a6d1d 100644 --- a/Tests/Translation/TranslatorTest.php +++ b/Tests/Translation/TranslatorTest.php @@ -15,7 +15,7 @@ use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Translation\Exception\InvalidArgumentException; use Symfony\Component\Translation\Formatter\MessageFormatter; @@ -117,8 +117,7 @@ public function testLoadResourcesWithoutCaching() public function testGetDefaultLocale() { - $container = $this->createMock(\Psr\Container\ContainerInterface::class); - $translator = new Translator($container, new MessageFormatter(), 'en'); + $translator = new Translator(new Container(), new MessageFormatter(), 'en'); $this->assertSame('en', $translator->getLocale()); } @@ -127,9 +126,8 @@ public function testInvalidOptions() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The Translator does not support the following options: \'foo\''); - $container = $this->createMock(ContainerInterface::class); - new Translator($container, new MessageFormatter(), 'en', [], ['foo' => 'bar']); + new Translator(new Container(), new MessageFormatter(), 'en', [], ['foo' => 'bar']); } /** @dataProvider getDebugModeAndCacheDirCombinations */ @@ -294,12 +292,9 @@ protected function getLoader() protected function getContainer($loader) { - $container = $this->createMock(ContainerInterface::class); - $container - ->expects($this->any()) - ->method('get') - ->willReturn($loader) - ; + $container = new Container(); + $container->set('loader', $loader); + $container->set('yml', $loader); return $container; } From 14b251e9110b838c9798e2757f1e473a8f478ad6 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Tue, 16 Jan 2024 01:52:38 +0100 Subject: [PATCH 056/180] [FrameworkBundle] Remove redundant check from test --- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 0d97dcf62..8247d3fa7 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -38,7 +38,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; @@ -1930,9 +1929,6 @@ public function testHttpClientOverrideDefaultOptions() public function testHttpClientRetry() { - if (!class_exists(RetryableHttpClient::class)) { - $this->expectException(LogicException::class); - } $container = $this->createContainerFromFile('http_client_retry'); $this->assertSame([429, 500 => ['GET', 'HEAD']], $container->getDefinition('http_client.retry_strategy')->getArgument(0)); From a6b88545b54ab2cc0b09f40aeacfcf408449806b Mon Sep 17 00:00:00 2001 From: HypeMC Date: Mon, 29 Jan 2024 10:12:01 +0100 Subject: [PATCH 057/180] [FrameworkBundle] Remove redundant `name` attribute from `default_context` --- DependencyInjection/Configuration.php | 1 - 1 file changed, 1 deletion(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 7547b192f..1a9916ed7 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1116,7 +1116,6 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e ->end() ->arrayNode('default_context') ->normalizeKeys(false) - ->useAttributeAsKey('name') ->beforeNormalization() ->ifTrue(fn () => $this->debug && class_exists(JsonParser::class)) ->then(fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) From 8f2a6982e8e0b205413ff97205b9d25adc20029b Mon Sep 17 00:00:00 2001 From: Ramunas Pabreza Date: Fri, 19 Jan 2024 12:11:02 +0200 Subject: [PATCH 058/180] Mailersend webhook remote event --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/mailer_webhook.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index cf8bb8dfc..095d782aa 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2589,6 +2589,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co if ($webhookEnabled) { $webhookRequestParsers = [ MailerBridge\Brevo\Webhook\BrevoRequestParser::class => 'mailer.webhook.request_parser.brevo', + MailerBridge\MailerSend\Webhook\MailerSendRequestParser::class => 'mailer.webhook.request_parser.mailersend', MailerBridge\Mailgun\Webhook\MailgunRequestParser::class => 'mailer.webhook.request_parser.mailgun', MailerBridge\Mailjet\Webhook\MailjetRequestParser::class => 'mailer.webhook.request_parser.mailjet', MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark', diff --git a/Resources/config/mailer_webhook.php b/Resources/config/mailer_webhook.php index 5c1014713..f9d2b9686 100644 --- a/Resources/config/mailer_webhook.php +++ b/Resources/config/mailer_webhook.php @@ -13,6 +13,8 @@ use Symfony\Component\Mailer\Bridge\Brevo\RemoteEvent\BrevoPayloadConverter; use Symfony\Component\Mailer\Bridge\Brevo\Webhook\BrevoRequestParser; +use Symfony\Component\Mailer\Bridge\MailerSend\RemoteEvent\MailerSendPayloadConverter; +use Symfony\Component\Mailer\Bridge\MailerSend\Webhook\MailerSendRequestParser; use Symfony\Component\Mailer\Bridge\Mailgun\RemoteEvent\MailgunPayloadConverter; use Symfony\Component\Mailer\Bridge\Mailgun\Webhook\MailgunRequestParser; use Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent\MailjetPayloadConverter; @@ -31,6 +33,11 @@ ->args([service('mailer.payload_converter.brevo')]) ->alias(BrevoRequestParser::class, 'mailer.webhook.request_parser.brevo') + ->set('mailer.payload_converter.mailersend', MailerSendPayloadConverter::class) + ->set('mailer.webhook.request_parser.mailersend', MailerSendRequestParser::class) + ->args([service('mailer.payload_converter.mailersend')]) + ->alias(MailerSendRequestParser::class, 'mailer.webhook.request_parser.mailersend') + ->set('mailer.payload_converter.mailgun', MailgunPayloadConverter::class) ->set('mailer.webhook.request_parser.mailgun', MailgunRequestParser::class) ->args([service('mailer.payload_converter.mailgun')]) From f96384a74ad810fa702b896010d38c78622744d3 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Tue, 9 Jan 2024 08:02:56 +0100 Subject: [PATCH 059/180] Add `SecretsRevealCommand` --- CHANGELOG.md | 1 + Command/SecretsRevealCommand.php | 72 ++++++++++++++++++ DependencyInjection/FrameworkExtension.php | 1 + Resources/config/console.php | 8 ++ Tests/Command/SecretsRevealCommandTest.php | 86 ++++++++++++++++++++++ 5 files changed, 168 insertions(+) create mode 100644 Command/SecretsRevealCommand.php create mode 100644 Tests/Command/SecretsRevealCommandTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d7f6295..cc2151d6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * Move the Router `cache_dir` to `kernel.build_dir` * Deprecate the `router.cache_dir` config option * Add `rate_limiter` tags to rate limiter services + * Add `secrets:reveal` command 7.0 --- diff --git a/Command/SecretsRevealCommand.php b/Command/SecretsRevealCommand.php new file mode 100644 index 000000000..bcbdea11f --- /dev/null +++ b/Command/SecretsRevealCommand.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @internal + */ +#[AsCommand(name: 'secrets:reveal', description: 'Reveal the value of a secret')] +final class SecretsRevealCommand extends Command +{ + public function __construct( + private readonly AbstractVault $vault, + private readonly ?AbstractVault $localVault = null, + ) { + parent::__construct(); + } + + protected function configure(): void + { + $this + ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret to reveal', null, fn () => array_keys($this->vault->list())) + ->setHelp(<<<'EOF' +The %command.name% command reveals a stored secret. + + %command.full_name% +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + + $secrets = $this->vault->list(true); + $localSecrets = $this->localVault?->list(true); + + $name = (string) $input->getArgument('name'); + + if (null !== $localSecrets && \array_key_exists($name, $localSecrets)) { + $io->writeln($localSecrets[$name]); + } else { + if (!\array_key_exists($name, $secrets)) { + $io->error(sprintf('The secret "%s" does not exist.', $name)); + + return self::INVALID; + } + + $io->writeln($secrets[$name]); + } + + return self::SUCCESS; + } +} diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 095d782aa..38de7421d 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1773,6 +1773,7 @@ private function registerSecretsConfiguration(array $config, ContainerBuilder $c if (!$this->readConfigEnabled('secrets', $container, $config)) { $container->removeDefinition('console.command.secrets_set'); $container->removeDefinition('console.command.secrets_list'); + $container->removeDefinition('console.command.secrets_reveal'); $container->removeDefinition('console.command.secrets_remove'); $container->removeDefinition('console.command.secrets_generate_key'); $container->removeDefinition('console.command.secrets_decrypt_to_local'); diff --git a/Resources/config/console.php b/Resources/config/console.php index 334d20426..b4f7dfcf3 100644 --- a/Resources/config/console.php +++ b/Resources/config/console.php @@ -33,6 +33,7 @@ use Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand; use Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand; use Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand; +use Symfony\Bundle\FrameworkBundle\Command\SecretsRevealCommand; use Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand; use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand; @@ -355,6 +356,13 @@ ]) ->tag('console.command') + ->set('console.command.secrets_reveal', SecretsRevealCommand::class) + ->args([ + service('secrets.vault'), + service('secrets.local_vault')->ignoreOnInvalid(), + ]) + ->tag('console.command') + ->set('console.command.secrets_decrypt_to_local', SecretsDecryptToLocalCommand::class) ->args([ service('secrets.vault'), diff --git a/Tests/Command/SecretsRevealCommandTest.php b/Tests/Command/SecretsRevealCommandTest.php new file mode 100644 index 000000000..94643db2c --- /dev/null +++ b/Tests/Command/SecretsRevealCommandTest.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Command\SecretsRevealCommand; +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Tester\CommandTester; + +class SecretsRevealCommandTest extends TestCase +{ + public function testExecute() + { + $vault = $this->createMock(AbstractVault::class); + $vault->method('list')->willReturn(['secretKey' => 'secretValue']); + + $command = new SecretsRevealCommand($vault); + + $tester = new CommandTester($command); + $this->assertSame(Command::SUCCESS, $tester->execute(['name' => 'secretKey'])); + + $this->assertEquals('secretValue', trim($tester->getDisplay(true))); + } + + public function testInvalidName() + { + $vault = $this->createMock(AbstractVault::class); + $vault->method('list')->willReturn(['secretKey' => 'secretValue']); + + $command = new SecretsRevealCommand($vault); + + $tester = new CommandTester($command); + $this->assertSame(Command::INVALID, $tester->execute(['name' => 'undefinedKey'])); + + $this->assertStringContainsString('The secret "undefinedKey" does not exist.', trim($tester->getDisplay(true))); + } + + /** + * @backupGlobals enabled + */ + public function testLocalVaultOverride() + { + $vault = $this->createMock(AbstractVault::class); + $vault->method('list')->willReturn(['secretKey' => 'secretValue']); + + $_ENV = ['secretKey' => 'newSecretValue']; + $localVault = new DotenvVault('/not/a/path'); + + $command = new SecretsRevealCommand($vault, $localVault); + + $tester = new CommandTester($command); + $this->assertSame(Command::SUCCESS, $tester->execute(['name' => 'secretKey'])); + + $this->assertEquals('newSecretValue', trim($tester->getDisplay(true))); + } + + /** + * @backupGlobals enabled + */ + public function testOnlyLocalVaultContainsName() + { + $vault = $this->createMock(AbstractVault::class); + $vault->method('list')->willReturn(['otherKey' => 'secretValue']); + + $_ENV = ['secretKey' => 'secretValue']; + $localVault = new DotenvVault('/not/a/path'); + + $command = new SecretsRevealCommand($vault, $localVault); + + $tester = new CommandTester($command); + $this->assertSame(Command::SUCCESS, $tester->execute(['name' => 'secretKey'])); + + $this->assertEquals('secretValue', trim($tester->getDisplay(true))); + } +} From ffcf3feb54e335efec2acb3f0a9dea0e57015124 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Tue, 16 Jan 2024 13:02:04 +0100 Subject: [PATCH 060/180] [FrameworkBundle][HttpClient] Add `ThrottlingHttpClient` to limit requests within a timeframe --- CHANGELOG.md | 1 + DependencyInjection/Configuration.php | 35 +++++++++++++--- DependencyInjection/FrameworkExtension.php | 33 +++++++++++++++ Resources/config/schema/symfony-1.0.xsd | 2 + .../DependencyInjection/ConfigurationTest.php | 40 +++++++++++++++++++ .../Fixtures/php/http_client_rate_limiter.php | 27 +++++++++++++ .../Fixtures/xml/http_client_rate_limiter.xml | 21 ++++++++++ .../Fixtures/yml/http_client_rate_limiter.yml | 19 +++++++++ .../FrameworkExtensionTestCase.php | 31 ++++++++++++++ 9 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 Tests/DependencyInjection/Fixtures/php/http_client_rate_limiter.php create mode 100644 Tests/DependencyInjection/Fixtures/xml/http_client_rate_limiter.xml create mode 100644 Tests/DependencyInjection/Fixtures/yml/http_client_rate_limiter.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index cc2151d6a..6fe797e3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * Deprecate the `router.cache_dir` config option * Add `rate_limiter` tags to rate limiter services * Add `secrets:reveal` command + * Add `rate_limiter` option to `http_client.default_options` and `http_client.scoped_clients` 7.0 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 1a9916ed7..c5efbc30f 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1715,17 +1715,32 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->fixXmlConfig('scoped_client') ->beforeNormalization() ->always(function ($config) { - if (empty($config['scoped_clients']) || !\is_array($config['default_options']['retry_failed'] ?? null)) { + if (empty($config['scoped_clients'])) { + return $config; + } + + $hasDefaultRateLimiter = isset($config['default_options']['rate_limiter']); + $hasDefaultRetryFailed = \is_array($config['default_options']['retry_failed'] ?? null); + + if (!$hasDefaultRateLimiter && !$hasDefaultRetryFailed) { return $config; } foreach ($config['scoped_clients'] as &$scopedConfig) { - if (!isset($scopedConfig['retry_failed']) || true === $scopedConfig['retry_failed']) { - $scopedConfig['retry_failed'] = $config['default_options']['retry_failed']; - continue; + if ($hasDefaultRateLimiter) { + if (!isset($scopedConfig['rate_limiter']) || true === $scopedConfig['rate_limiter']) { + $scopedConfig['rate_limiter'] = $config['default_options']['rate_limiter']; + } elseif (false === $scopedConfig['rate_limiter']) { + $scopedConfig['rate_limiter'] = null; + } } - if (\is_array($scopedConfig['retry_failed'])) { - $scopedConfig['retry_failed'] += $config['default_options']['retry_failed']; + + if ($hasDefaultRetryFailed) { + if (!isset($scopedConfig['retry_failed']) || true === $scopedConfig['retry_failed']) { + $scopedConfig['retry_failed'] = $config['default_options']['retry_failed']; + } elseif (\is_array($scopedConfig['retry_failed'])) { + $scopedConfig['retry_failed'] += $config['default_options']['retry_failed']; + } } } @@ -1830,6 +1845,10 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->normalizeKeys(false) ->variablePrototype()->end() ->end() + ->scalarNode('rate_limiter') + ->defaultNull() + ->info('Rate limiter name to use for throttling requests') + ->end() ->append($this->createHttpClientRetrySection()) ->end() ->end() @@ -1978,6 +1997,10 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->normalizeKeys(false) ->variablePrototype()->end() ->end() + ->scalarNode('rate_limiter') + ->defaultNull() + ->info('Rate limiter name to use for throttling requests') + ->end() ->append($this->createHttpClientRetrySection()) ->end() ->end() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 38de7421d..ff525bb5e 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -85,6 +85,7 @@ use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; use Symfony\Component\HttpClient\RetryableHttpClient; use Symfony\Component\HttpClient\ScopingHttpClient; +use Symfony\Component\HttpClient\ThrottlingHttpClient; use Symfony\Component\HttpClient\UriTemplateHttpClient; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Attribute\AsController; @@ -345,6 +346,7 @@ public function load(array $configs, ContainerBuilder $container): void } if ($this->readConfigEnabled('http_client', $container, $config['http_client'])) { + $this->readConfigEnabled('rate_limiter', $container, $config['rate_limiter']); // makes sure that isInitializedConfigEnabled() will work $this->registerHttpClientConfiguration($config['http_client'], $container, $loader); } @@ -2409,6 +2411,8 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder $loader->load('http_client.php'); $options = $config['default_options'] ?? []; + $rateLimiter = $options['rate_limiter'] ?? null; + unset($options['rate_limiter']); $retryOptions = $options['retry_failed'] ?? ['enabled' => false]; unset($options['retry_failed']); $defaultUriTemplateVars = $options['vars'] ?? []; @@ -2430,6 +2434,10 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder $container->removeAlias(HttpClient::class); } + if (null !== $rateLimiter) { + $this->registerThrottlingHttpClient($rateLimiter, 'http_client', $container); + } + if ($this->readConfigEnabled('http_client.retry_failed', $container, $retryOptions)) { $this->registerRetryableHttpClient($retryOptions, 'http_client', $container); } @@ -2451,6 +2459,8 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder $scope = $scopeConfig['scope'] ?? null; unset($scopeConfig['scope']); + $rateLimiter = $scopeConfig['rate_limiter'] ?? null; + unset($scopeConfig['rate_limiter']); $retryOptions = $scopeConfig['retry_failed'] ?? ['enabled' => false]; unset($scopeConfig['retry_failed']); @@ -2470,6 +2480,10 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder ; } + if (null !== $rateLimiter) { + $this->registerThrottlingHttpClient($rateLimiter, $name, $container); + } + if ($this->readConfigEnabled('http_client.scoped_clients.'.$name.'.retry_failed', $container, $retryOptions)) { $this->registerRetryableHttpClient($retryOptions, $name, $container); } @@ -2507,6 +2521,25 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder } } + private function registerThrottlingHttpClient(string $rateLimiter, string $name, ContainerBuilder $container): void + { + if (!class_exists(ThrottlingHttpClient::class)) { + throw new LogicException('Rate limiter support cannot be enabled as version 7.1+ of the HttpClient component is required.'); + } + + if (!$this->isInitializedConfigEnabled('rate_limiter')) { + throw new LogicException('Rate limiter cannot be used within HttpClient as the RateLimiter component is not enabled.'); + } + + $container->register($name.'.throttling.limiter', LimiterInterface::class) + ->setFactory([new Reference('limiter.'.$rateLimiter), 'create']); + + $container + ->register($name.'.throttling', ThrottlingHttpClient::class) + ->setDecoratedService($name, null, 15) // higher priority than RetryableHttpClient (10) + ->setArguments([new Reference($name.'.throttling.inner'), new Reference($name.'.throttling.limiter')]); + } + private function registerRetryableHttpClient(array $options, string $name, ContainerBuilder $container): void { if (null !== $options['retry_strategy']) { diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index 9279eaf68..8ddadcc78 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -661,6 +661,7 @@ + @@ -691,6 +692,7 @@ + diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index d56cfa90d..0c80a6f10 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -530,6 +530,46 @@ public function testEnabledLockNeedsResources() ]); } + public function testScopedHttpClientsInheritRateLimiterAndRetryFailedConfiguration() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $config = $processor->processConfiguration($configuration, [[ + 'http_client' => [ + 'default_options' => ['rate_limiter' => 'default_limiter', 'retry_failed' => ['max_retries' => 77]], + 'scoped_clients' => [ + 'foo' => ['base_uri' => 'http://example.com'], + 'bar' => ['base_uri' => 'http://example.com', 'rate_limiter' => true, 'retry_failed' => true], + 'baz' => ['base_uri' => 'http://example.com', 'rate_limiter' => false, 'retry_failed' => false], + 'qux' => ['base_uri' => 'http://example.com', 'rate_limiter' => 'foo_limiter', 'retry_failed' => ['max_retries' => 88, 'delay' => 999]], + ], + ], + ]]); + + $scopedClients = $config['http_client']['scoped_clients']; + + $this->assertSame('default_limiter', $scopedClients['foo']['rate_limiter']); + $this->assertTrue($scopedClients['foo']['retry_failed']['enabled']); + $this->assertSame(77, $scopedClients['foo']['retry_failed']['max_retries']); + $this->assertSame(1000, $scopedClients['foo']['retry_failed']['delay']); + + $this->assertSame('default_limiter', $scopedClients['bar']['rate_limiter']); + $this->assertTrue($scopedClients['bar']['retry_failed']['enabled']); + $this->assertSame(77, $scopedClients['bar']['retry_failed']['max_retries']); + $this->assertSame(1000, $scopedClients['bar']['retry_failed']['delay']); + + $this->assertNull($scopedClients['baz']['rate_limiter']); + $this->assertFalse($scopedClients['baz']['retry_failed']['enabled']); + $this->assertSame(3, $scopedClients['baz']['retry_failed']['max_retries']); + $this->assertSame(1000, $scopedClients['baz']['retry_failed']['delay']); + + $this->assertSame('foo_limiter', $scopedClients['qux']['rate_limiter']); + $this->assertTrue($scopedClients['qux']['retry_failed']['enabled']); + $this->assertSame(88, $scopedClients['qux']['retry_failed']['max_retries']); + $this->assertSame(999, $scopedClients['qux']['retry_failed']['delay']); + } + protected static function getBundleDefaultConfig() { return [ diff --git a/Tests/DependencyInjection/Fixtures/php/http_client_rate_limiter.php b/Tests/DependencyInjection/Fixtures/php/http_client_rate_limiter.php new file mode 100644 index 000000000..c8256d913 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/php/http_client_rate_limiter.php @@ -0,0 +1,27 @@ +loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'rate_limiter' => [ + 'foo_limiter' => [ + 'lock_factory' => null, + 'policy' => 'token_bucket', + 'limit' => 10, + 'rate' => ['interval' => '5 seconds', 'amount' => 10], + ], + ], + 'http_client' => [ + 'default_options' => [ + 'rate_limiter' => 'default_limiter', + ], + 'scoped_clients' => [ + 'foo' => [ + 'base_uri' => 'http://example.com', + 'rate_limiter' => 'foo_limiter', + ], + ], + ], +]); diff --git a/Tests/DependencyInjection/Fixtures/xml/http_client_rate_limiter.xml b/Tests/DependencyInjection/Fixtures/xml/http_client_rate_limiter.xml new file mode 100644 index 000000000..8c9dbcdad --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/xml/http_client_rate_limiter.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/Tests/DependencyInjection/Fixtures/yml/http_client_rate_limiter.yml b/Tests/DependencyInjection/Fixtures/yml/http_client_rate_limiter.yml new file mode 100644 index 000000000..6376192b7 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/yml/http_client_rate_limiter.yml @@ -0,0 +1,19 @@ +framework: + annotations: false + http_method_override: false + handle_all_throwables: true + php_errors: + log: true + rate_limiter: + foo_limiter: + lock_factory: null + policy: token_bucket + limit: 10 + rate: { interval: '5 seconds', amount: 10 } + http_client: + default_options: + rate_limiter: default_limiter + scoped_clients: + foo: + base_uri: http://example.com + rate_limiter: foo_limiter diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 3d1e9c29b..7cde707c5 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -38,6 +38,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; @@ -51,6 +52,7 @@ use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\RetryableHttpClient; use Symfony\Component\HttpClient\ScopingHttpClient; +use Symfony\Component\HttpClient\ThrottlingHttpClient; use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; @@ -1986,6 +1988,35 @@ public function testHttpClientFullDefaultOptions() $this->assertSame(['foo' => ['bar' => 'baz']], $defaultOptions['extra']); } + public function testHttpClientRateLimiter() + { + if (!class_exists(ThrottlingHttpClient::class)) { + $this->expectException(LogicException::class); + } + + $container = $this->createContainerFromFile('http_client_rate_limiter'); + + $this->assertTrue($container->hasDefinition('http_client.throttling')); + $definition = $container->getDefinition('http_client.throttling'); + $this->assertSame(ThrottlingHttpClient::class, $definition->getClass()); + $this->assertSame('http_client', $definition->getDecoratedService()[0]); + $this->assertCount(2, $arguments = $definition->getArguments()); + $this->assertInstanceOf(Reference::class, $arguments[0]); + $this->assertSame('http_client.throttling.inner', (string) $arguments[0]); + $this->assertInstanceOf(Reference::class, $arguments[1]); + $this->assertSame('http_client.throttling.limiter', (string) $arguments[1]); + + $this->assertTrue($container->hasDefinition('foo.throttling')); + $definition = $container->getDefinition('foo.throttling'); + $this->assertSame(ThrottlingHttpClient::class, $definition->getClass()); + $this->assertSame('foo', $definition->getDecoratedService()[0]); + $this->assertCount(2, $arguments = $definition->getArguments()); + $this->assertInstanceOf(Reference::class, $arguments[0]); + $this->assertSame('foo.throttling.inner', (string) $arguments[0]); + $this->assertInstanceOf(Reference::class, $arguments[1]); + $this->assertSame('foo.throttling.limiter', (string) $arguments[1]); + } + public static function provideMailer(): array { return [ From e16613811d4b0f9d7a78750d910e0e5b8eccc2dd Mon Sep 17 00:00:00 2001 From: Nicolas Valverde <64469669+n-valverde@users.noreply.github.com> Date: Thu, 22 Jun 2023 15:26:14 +0200 Subject: [PATCH 061/180] [DependencyInjection] Add `CheckAliasValidityPass` to check interface compatibility --- CHANGELOG.md | 1 + Command/ContainerLintCommand.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fe797e3a..950c2b8c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.1 --- + * Add `CheckAliasValidityPass` to `lint:container` command * Add `private_ranges` as a shortcut for private IP address ranges to the `trusted_proxies` option * Mark classes `ConfigBuilderCacheWarmer`, `Router`, `SerializerCacheWarmer`, `TranslationsCacheWarmer`, `Translator` and `ValidatorCacheWarmer` as `final` * Move the Router `cache_dir` to `kernel.build_dir` diff --git a/Command/ContainerLintCommand.php b/Command/ContainerLintCommand.php index b63ebe431..cd6e0657c 100644 --- a/Command/ContainerLintCommand.php +++ b/Command/ContainerLintCommand.php @@ -19,6 +19,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\Compiler\CheckAliasValidityPass; use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Compiler\ResolveFactoryClassPass; @@ -107,6 +108,7 @@ private function getContainerBuilder(): ContainerBuilder $container->setParameter('container.build_hash', 'lint_container'); $container->setParameter('container.build_id', 'lint_container'); + $container->addCompilerPass(new CheckAliasValidityPass(), PassConfig::TYPE_BEFORE_REMOVING, -100); $container->addCompilerPass(new CheckTypeDeclarationsPass(true), PassConfig::TYPE_AFTER_REMOVING, -100); return $this->container = $container; From 8966e1c9730dd9b4ac56ea7fdbcb0642a8eb2f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 8 Feb 2024 18:09:44 +0100 Subject: [PATCH 062/180] [workflow] determines places form transitions --- DependencyInjection/Configuration.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index e5b15e88f..d02e85fe1 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -486,8 +486,6 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void return array_values($places); }) ->end() - ->isRequired() - ->requiresAtLeastOneElement() ->prototype('array') ->children() ->scalarNode('name') From 427ab31004594fc33be53edff3465451739bcc6b Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 8 Feb 2024 16:14:05 +0100 Subject: [PATCH 063/180] [FrameworkBundle] Use CPP --- CacheWarmer/AbstractPhpFileCacheWarmer.php | 8 ++---- CacheWarmer/SerializerCacheWarmer.php | 9 +++--- CacheWarmer/ValidatorCacheWarmer.php | 9 +++--- Command/AssetsInstallCommand.php | 12 +++----- Command/CacheClearCommand.php | 8 +++--- Command/CachePoolClearCommand.php | 12 +++----- Command/CachePoolDeleteCommand.php | 12 +++----- Command/CachePoolInvalidateTagsCommand.php | 7 ++--- Command/CachePoolListCommand.php | 9 ++---- Command/CachePoolPruneCommand.php | 9 ++---- Command/CacheWarmupCommand.php | 9 ++---- Command/DebugAutowiringCommand.php | 9 +++--- Command/EventDispatcherDebugCommand.php | 9 ++---- Command/RouterDebugCommand.php | 12 +++----- Command/RouterMatchCommand.php | 12 +++----- Command/SecretsDecryptToLocalCommand.php | 12 +++----- Command/SecretsEncryptFromLocalCommand.php | 12 +++----- Command/SecretsGenerateKeysCommand.php | 12 +++----- Command/SecretsListCommand.php | 12 +++----- Command/SecretsRemoveCommand.php | 12 +++----- Command/SecretsSetCommand.php | 12 +++----- Command/TranslationDebugCommand.php | 30 +++++++------------- Command/TranslationUpdateCommand.php | 33 ++++++++-------------- Console/Application.php | 8 ++---- Console/Descriptor/TextDescriptor.php | 8 ++---- Controller/RedirectController.php | 14 ++++----- Controller/TemplateController.php | 8 ++---- DependencyInjection/Configuration.php | 8 ++---- HttpCache/HttpCache.php | 12 ++++---- Routing/DelegatingLoader.php | 12 ++++---- Secrets/DotenvVault.php | 7 ++--- Test/TestBrowserToken.php | 11 ++++---- Translation/Translator.php | 23 +++++++-------- 33 files changed, 145 insertions(+), 247 deletions(-) diff --git a/CacheWarmer/AbstractPhpFileCacheWarmer.php b/CacheWarmer/AbstractPhpFileCacheWarmer.php index 3d7c99e4f..d809888be 100644 --- a/CacheWarmer/AbstractPhpFileCacheWarmer.php +++ b/CacheWarmer/AbstractPhpFileCacheWarmer.php @@ -19,14 +19,12 @@ abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface { - private string $phpArrayFile; - /** * @param string $phpArrayFile The PHP file where metadata are cached */ - public function __construct(string $phpArrayFile) - { - $this->phpArrayFile = $phpArrayFile; + public function __construct( + private string $phpArrayFile, + ) { } public function isOptional(): bool diff --git a/CacheWarmer/SerializerCacheWarmer.php b/CacheWarmer/SerializerCacheWarmer.php index 228a763fe..46da4daaa 100644 --- a/CacheWarmer/SerializerCacheWarmer.php +++ b/CacheWarmer/SerializerCacheWarmer.php @@ -28,16 +28,15 @@ */ class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer { - private array $loaders; - /** * @param LoaderInterface[] $loaders The serializer metadata loaders * @param string $phpArrayFile The PHP file where metadata are cached */ - public function __construct(array $loaders, string $phpArrayFile) - { + public function __construct( + private array $loaders, + string $phpArrayFile, + ) { parent::__construct($phpArrayFile); - $this->loaders = $loaders; } protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, ?string $buildDir = null): bool diff --git a/CacheWarmer/ValidatorCacheWarmer.php b/CacheWarmer/ValidatorCacheWarmer.php index abf350562..6ecaa4bd1 100644 --- a/CacheWarmer/ValidatorCacheWarmer.php +++ b/CacheWarmer/ValidatorCacheWarmer.php @@ -29,15 +29,14 @@ */ class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer { - private ValidatorBuilder $validatorBuilder; - /** * @param string $phpArrayFile The PHP file where metadata are cached */ - public function __construct(ValidatorBuilder $validatorBuilder, string $phpArrayFile) - { + public function __construct( + private ValidatorBuilder $validatorBuilder, + string $phpArrayFile, + ) { parent::__construct($phpArrayFile); - $this->validatorBuilder = $validatorBuilder; } protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter, ?string $buildDir = null): bool diff --git a/Command/AssetsInstallCommand.php b/Command/AssetsInstallCommand.php index 264955d79..cb05fe827 100644 --- a/Command/AssetsInstallCommand.php +++ b/Command/AssetsInstallCommand.php @@ -41,15 +41,11 @@ class AssetsInstallCommand extends Command public const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; public const METHOD_RELATIVE_SYMLINK = 'relative symlink'; - private Filesystem $filesystem; - private string $projectDir; - - public function __construct(Filesystem $filesystem, string $projectDir) - { + public function __construct( + private Filesystem $filesystem, + private string $projectDir, + ) { parent::__construct(); - - $this->filesystem = $filesystem; - $this->projectDir = $projectDir; } protected function configure(): void diff --git a/Command/CacheClearCommand.php b/Command/CacheClearCommand.php index 40880df47..6f5510169 100644 --- a/Command/CacheClearCommand.php +++ b/Command/CacheClearCommand.php @@ -37,14 +37,14 @@ #[AsCommand(name: 'cache:clear', description: 'Clear the cache')] class CacheClearCommand extends Command { - private CacheClearerInterface $cacheClearer; private Filesystem $filesystem; - public function __construct(CacheClearerInterface $cacheClearer, ?Filesystem $filesystem = null) - { + public function __construct( + private CacheClearerInterface $cacheClearer, + ?Filesystem $filesystem = null, + ) { parent::__construct(); - $this->cacheClearer = $cacheClearer; $this->filesystem = $filesystem ?? new Filesystem(); } diff --git a/Command/CachePoolClearCommand.php b/Command/CachePoolClearCommand.php index 8b8b9cd35..d5320e7a9 100644 --- a/Command/CachePoolClearCommand.php +++ b/Command/CachePoolClearCommand.php @@ -32,18 +32,14 @@ #[AsCommand(name: 'cache:pool:clear', description: 'Clear cache pools')] final class CachePoolClearCommand extends Command { - private Psr6CacheClearer $poolClearer; - private ?array $poolNames; - /** * @param string[]|null $poolNames */ - public function __construct(Psr6CacheClearer $poolClearer, ?array $poolNames = null) - { + public function __construct( + private Psr6CacheClearer $poolClearer, + private ?array $poolNames = null, + ) { parent::__construct(); - - $this->poolClearer = $poolClearer; - $this->poolNames = $poolNames; } protected function configure(): void diff --git a/Command/CachePoolDeleteCommand.php b/Command/CachePoolDeleteCommand.php index dfa307bc0..e634e00f0 100644 --- a/Command/CachePoolDeleteCommand.php +++ b/Command/CachePoolDeleteCommand.php @@ -29,18 +29,14 @@ #[AsCommand(name: 'cache:pool:delete', description: 'Delete an item from a cache pool')] final class CachePoolDeleteCommand extends Command { - private Psr6CacheClearer $poolClearer; - private ?array $poolNames; - /** * @param string[]|null $poolNames */ - public function __construct(Psr6CacheClearer $poolClearer, ?array $poolNames = null) - { + public function __construct( + private Psr6CacheClearer $poolClearer, + private ?array $poolNames = null, + ) { parent::__construct(); - - $this->poolClearer = $poolClearer; - $this->poolNames = $poolNames; } protected function configure(): void diff --git a/Command/CachePoolInvalidateTagsCommand.php b/Command/CachePoolInvalidateTagsCommand.php index 9e6ef9330..f879a6d0d 100644 --- a/Command/CachePoolInvalidateTagsCommand.php +++ b/Command/CachePoolInvalidateTagsCommand.php @@ -30,14 +30,13 @@ #[AsCommand(name: 'cache:pool:invalidate-tags', description: 'Invalidate cache tags for all or a specific pool')] final class CachePoolInvalidateTagsCommand extends Command { - private ServiceProviderInterface $pools; private array $poolNames; - public function __construct(ServiceProviderInterface $pools) - { + public function __construct( + private ServiceProviderInterface $pools, + ) { parent::__construct(); - $this->pools = $pools; $this->poolNames = array_keys($pools->getProvidedServices()); } diff --git a/Command/CachePoolListCommand.php b/Command/CachePoolListCommand.php index 2659ad8fe..6b8e71eb0 100644 --- a/Command/CachePoolListCommand.php +++ b/Command/CachePoolListCommand.php @@ -25,16 +25,13 @@ #[AsCommand(name: 'cache:pool:list', description: 'List available cache pools')] final class CachePoolListCommand extends Command { - private array $poolNames; - /** * @param string[] $poolNames */ - public function __construct(array $poolNames) - { + public function __construct( + private array $poolNames, + ) { parent::__construct(); - - $this->poolNames = $poolNames; } protected function configure(): void diff --git a/Command/CachePoolPruneCommand.php b/Command/CachePoolPruneCommand.php index fc0dc6d79..fba1033f9 100644 --- a/Command/CachePoolPruneCommand.php +++ b/Command/CachePoolPruneCommand.php @@ -26,16 +26,13 @@ #[AsCommand(name: 'cache:pool:prune', description: 'Prune cache pools')] final class CachePoolPruneCommand extends Command { - private iterable $pools; - /** * @param iterable $pools */ - public function __construct(iterable $pools) - { + public function __construct( + private iterable $pools, + ) { parent::__construct(); - - $this->pools = $pools; } protected function configure(): void diff --git a/Command/CacheWarmupCommand.php b/Command/CacheWarmupCommand.php index 6f1073de4..a4b32a561 100644 --- a/Command/CacheWarmupCommand.php +++ b/Command/CacheWarmupCommand.php @@ -31,13 +31,10 @@ #[AsCommand(name: 'cache:warmup', description: 'Warm up an empty cache')] class CacheWarmupCommand extends Command { - private CacheWarmerAggregate $cacheWarmer; - - public function __construct(CacheWarmerAggregate $cacheWarmer) - { + public function __construct( + private CacheWarmerAggregate $cacheWarmer, + ) { parent::__construct(); - - $this->cacheWarmer = $cacheWarmer; } protected function configure(): void diff --git a/Command/DebugAutowiringCommand.php b/Command/DebugAutowiringCommand.php index f6efd8bef..77011b185 100644 --- a/Command/DebugAutowiringCommand.php +++ b/Command/DebugAutowiringCommand.php @@ -33,11 +33,10 @@ #[AsCommand(name: 'debug:autowiring', description: 'List classes/interfaces you can use for autowiring')] class DebugAutowiringCommand extends ContainerDebugCommand { - private ?FileLinkFormatter $fileLinkFormatter; - - public function __construct(?string $name = null, ?FileLinkFormatter $fileLinkFormatter = null) - { - $this->fileLinkFormatter = $fileLinkFormatter; + public function __construct( + ?string $name = null, + private ?FileLinkFormatter $fileLinkFormatter = null, + ) { parent::__construct($name); } diff --git a/Command/EventDispatcherDebugCommand.php b/Command/EventDispatcherDebugCommand.php index 1a74e8682..52816e7de 100644 --- a/Command/EventDispatcherDebugCommand.php +++ b/Command/EventDispatcherDebugCommand.php @@ -37,13 +37,10 @@ class EventDispatcherDebugCommand extends Command { private const DEFAULT_DISPATCHER = 'event_dispatcher'; - private ContainerInterface $dispatchers; - - public function __construct(ContainerInterface $dispatchers) - { + public function __construct( + private ContainerInterface $dispatchers, + ) { parent::__construct(); - - $this->dispatchers = $dispatchers; } protected function configure(): void diff --git a/Command/RouterDebugCommand.php b/Command/RouterDebugCommand.php index 9318b46be..54df49431 100644 --- a/Command/RouterDebugCommand.php +++ b/Command/RouterDebugCommand.php @@ -39,15 +39,11 @@ class RouterDebugCommand extends Command { use BuildDebugContainerTrait; - private RouterInterface $router; - private ?FileLinkFormatter $fileLinkFormatter; - - public function __construct(RouterInterface $router, ?FileLinkFormatter $fileLinkFormatter = null) - { + public function __construct( + private RouterInterface $router, + private ?FileLinkFormatter $fileLinkFormatter = null, + ) { parent::__construct(); - - $this->router = $router; - $this->fileLinkFormatter = $fileLinkFormatter; } protected function configure(): void diff --git a/Command/RouterMatchCommand.php b/Command/RouterMatchCommand.php index 7efd1f3ed..475b403ca 100644 --- a/Command/RouterMatchCommand.php +++ b/Command/RouterMatchCommand.php @@ -33,18 +33,14 @@ #[AsCommand(name: 'router:match', description: 'Help debug routes by simulating a path info match')] class RouterMatchCommand extends Command { - private RouterInterface $router; - private iterable $expressionLanguageProviders; - /** * @param iterable $expressionLanguageProviders */ - public function __construct(RouterInterface $router, iterable $expressionLanguageProviders = []) - { + public function __construct( + private RouterInterface $router, + private iterable $expressionLanguageProviders = [], + ) { parent::__construct(); - - $this->router = $router; - $this->expressionLanguageProviders = $expressionLanguageProviders; } protected function configure(): void diff --git a/Command/SecretsDecryptToLocalCommand.php b/Command/SecretsDecryptToLocalCommand.php index ac711e3db..f76e1d05a 100644 --- a/Command/SecretsDecryptToLocalCommand.php +++ b/Command/SecretsDecryptToLocalCommand.php @@ -28,14 +28,10 @@ #[AsCommand(name: 'secrets:decrypt-to-local', description: 'Decrypt all secrets and stores them in the local vault')] final class SecretsDecryptToLocalCommand extends Command { - private AbstractVault $vault; - private ?AbstractVault $localVault; - - public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - + public function __construct( + private AbstractVault $vault, + private ?AbstractVault $localVault = null, + ) { parent::__construct(); } diff --git a/Command/SecretsEncryptFromLocalCommand.php b/Command/SecretsEncryptFromLocalCommand.php index 46e0baffc..9740098e5 100644 --- a/Command/SecretsEncryptFromLocalCommand.php +++ b/Command/SecretsEncryptFromLocalCommand.php @@ -27,14 +27,10 @@ #[AsCommand(name: 'secrets:encrypt-from-local', description: 'Encrypt all local secrets to the vault')] final class SecretsEncryptFromLocalCommand extends Command { - private AbstractVault $vault; - private ?AbstractVault $localVault; - - public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - + public function __construct( + private AbstractVault $vault, + private ?AbstractVault $localVault = null, + ) { parent::__construct(); } diff --git a/Command/SecretsGenerateKeysCommand.php b/Command/SecretsGenerateKeysCommand.php index 989eff9fd..66a752eac 100644 --- a/Command/SecretsGenerateKeysCommand.php +++ b/Command/SecretsGenerateKeysCommand.php @@ -30,14 +30,10 @@ #[AsCommand(name: 'secrets:generate-keys', description: 'Generate new encryption keys')] final class SecretsGenerateKeysCommand extends Command { - private AbstractVault $vault; - private ?AbstractVault $localVault; - - public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - + public function __construct( + private AbstractVault $vault, + private ?AbstractVault $localVault = null, + ) { parent::__construct(); } diff --git a/Command/SecretsListCommand.php b/Command/SecretsListCommand.php index 9a24f4a90..cdfc51c39 100644 --- a/Command/SecretsListCommand.php +++ b/Command/SecretsListCommand.php @@ -31,14 +31,10 @@ #[AsCommand(name: 'secrets:list', description: 'List all secrets')] final class SecretsListCommand extends Command { - private AbstractVault $vault; - private ?AbstractVault $localVault; - - public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - + public function __construct( + private AbstractVault $vault, + private ?AbstractVault $localVault = null, + ) { parent::__construct(); } diff --git a/Command/SecretsRemoveCommand.php b/Command/SecretsRemoveCommand.php index 1789f2981..11660b00d 100644 --- a/Command/SecretsRemoveCommand.php +++ b/Command/SecretsRemoveCommand.php @@ -32,14 +32,10 @@ #[AsCommand(name: 'secrets:remove', description: 'Remove a secret from the vault')] final class SecretsRemoveCommand extends Command { - private AbstractVault $vault; - private ?AbstractVault $localVault; - - public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - + public function __construct( + private AbstractVault $vault, + private ?AbstractVault $localVault = null, + ) { parent::__construct(); } diff --git a/Command/SecretsSetCommand.php b/Command/SecretsSetCommand.php index 2d2b8c5cb..49a20af76 100644 --- a/Command/SecretsSetCommand.php +++ b/Command/SecretsSetCommand.php @@ -33,14 +33,10 @@ #[AsCommand(name: 'secrets:set', description: 'Set a secret in the vault')] final class SecretsSetCommand extends Command { - private AbstractVault $vault; - private ?AbstractVault $localVault; - - public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - + public function __construct( + private AbstractVault $vault, + private ?AbstractVault $localVault = null, + ) { parent::__construct(); } diff --git a/Command/TranslationDebugCommand.php b/Command/TranslationDebugCommand.php index 7095d70ab..2438d3feb 100644 --- a/Command/TranslationDebugCommand.php +++ b/Command/TranslationDebugCommand.php @@ -50,27 +50,17 @@ class TranslationDebugCommand extends Command public const MESSAGE_UNUSED = 1; public const MESSAGE_EQUALS_FALLBACK = 2; - private TranslatorInterface $translator; - private TranslationReaderInterface $reader; - private ExtractorInterface $extractor; - private ?string $defaultTransPath; - private ?string $defaultViewsPath; - private array $transPaths; - private array $codePaths; - private array $enabledLocales; - - public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, ?string $defaultTransPath = null, ?string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) - { + public function __construct( + private TranslatorInterface $translator, + private TranslationReaderInterface $reader, + private ExtractorInterface $extractor, + private ?string $defaultTransPath = null, + private ?string $defaultViewsPath = null, + private array $transPaths = [], + private array $codePaths = [], + private array $enabledLocales = [], + ) { parent::__construct(); - - $this->translator = $translator; - $this->reader = $reader; - $this->extractor = $extractor; - $this->defaultTransPath = $defaultTransPath; - $this->defaultViewsPath = $defaultViewsPath; - $this->transPaths = $transPaths; - $this->codePaths = $codePaths; - $this->enabledLocales = $enabledLocales; } protected function configure(): void diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index fc95e0217..1a883f81e 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -50,29 +50,18 @@ class TranslationUpdateCommand extends Command 'xlf20' => ['xlf', '2.0'], ]; - private TranslationWriterInterface $writer; - private TranslationReaderInterface $reader; - private ExtractorInterface $extractor; - private string $defaultLocale; - private ?string $defaultTransPath; - private ?string $defaultViewsPath; - private array $transPaths; - private array $codePaths; - private array $enabledLocales; - - public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, ?string $defaultTransPath = null, ?string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) - { + public function __construct( + private TranslationWriterInterface $writer, + private TranslationReaderInterface $reader, + private ExtractorInterface $extractor, + private string $defaultLocale, + private ?string $defaultTransPath = null, + private ?string $defaultViewsPath = null, + private array $transPaths = [], + private array $codePaths = [], + private array $enabledLocales = [], + ) { parent::__construct(); - - $this->writer = $writer; - $this->reader = $reader; - $this->extractor = $extractor; - $this->defaultLocale = $defaultLocale; - $this->defaultTransPath = $defaultTransPath; - $this->defaultViewsPath = $defaultViewsPath; - $this->transPaths = $transPaths; - $this->codePaths = $codePaths; - $this->enabledLocales = $enabledLocales; } protected function configure(): void diff --git a/Console/Application.php b/Console/Application.php index 14a907e2e..1c41849e7 100644 --- a/Console/Application.php +++ b/Console/Application.php @@ -30,14 +30,12 @@ */ class Application extends BaseApplication { - private KernelInterface $kernel; private bool $commandsRegistered = false; private array $registrationErrors = []; - public function __construct(KernelInterface $kernel) - { - $this->kernel = $kernel; - + public function __construct( + private KernelInterface $kernel, + ) { parent::__construct('Symfony', Kernel::VERSION); $inputDefinition = $this->getDefinition(); diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index 1ce0539da..8a3c58708 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -38,11 +38,9 @@ */ class TextDescriptor extends Descriptor { - private ?FileLinkFormatter $fileLinkFormatter; - - public function __construct(?FileLinkFormatter $fileLinkFormatter = null) - { - $this->fileLinkFormatter = $fileLinkFormatter; + public function __construct( + private ?FileLinkFormatter $fileLinkFormatter = null, + ) { } protected function describeRouteCollection(RouteCollection $routes, array $options = []): void diff --git a/Controller/RedirectController.php b/Controller/RedirectController.php index fbb52ead7..1001fad63 100644 --- a/Controller/RedirectController.php +++ b/Controller/RedirectController.php @@ -27,15 +27,11 @@ */ class RedirectController { - private ?UrlGeneratorInterface $router; - private ?int $httpPort; - private ?int $httpsPort; - - public function __construct(?UrlGeneratorInterface $router = null, ?int $httpPort = null, ?int $httpsPort = null) - { - $this->router = $router; - $this->httpPort = $httpPort; - $this->httpsPort = $httpsPort; + public function __construct( + private ?UrlGeneratorInterface $router = null, + private ?int $httpPort = null, + private ?int $httpsPort = null, + ) { } /** diff --git a/Controller/TemplateController.php b/Controller/TemplateController.php index 97631572c..bcbcc382d 100644 --- a/Controller/TemplateController.php +++ b/Controller/TemplateController.php @@ -23,11 +23,9 @@ */ class TemplateController { - private ?Environment $twig; - - public function __construct(?Environment $twig = null) - { - $this->twig = $twig; + public function __construct( + private ?Environment $twig = null, + ) { } /** diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index e5b15e88f..722984e53 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -56,14 +56,12 @@ */ class Configuration implements ConfigurationInterface { - private bool $debug; - /** * @param bool $debug Whether debugging is enabled or not */ - public function __construct(bool $debug) - { - $this->debug = $debug; + public function __construct( + private bool $debug, + ) { } /** diff --git a/HttpCache/HttpCache.php b/HttpCache/HttpCache.php index 38eee7361..f163708cc 100644 --- a/HttpCache/HttpCache.php +++ b/HttpCache/HttpCache.php @@ -28,19 +28,19 @@ class HttpCache extends BaseHttpCache { protected ?string $cacheDir = null; - protected KernelInterface $kernel; private ?StoreInterface $store = null; - private ?SurrogateInterface $surrogate; private array $options; /** * @param $cache The cache directory (default used if null) or the storage instance */ - public function __construct(KernelInterface $kernel, string|StoreInterface|null $cache = null, ?SurrogateInterface $surrogate = null, ?array $options = null) - { - $this->kernel = $kernel; - $this->surrogate = $surrogate; + public function __construct( + protected KernelInterface $kernel, + string|StoreInterface|null $cache = null, + private ?SurrogateInterface $surrogate = null, + ?array $options = null, + ) { $this->options = $options ?? []; if ($cache instanceof StoreInterface) { diff --git a/Routing/DelegatingLoader.php b/Routing/DelegatingLoader.php index 3239d1094..42d461773 100644 --- a/Routing/DelegatingLoader.php +++ b/Routing/DelegatingLoader.php @@ -29,14 +29,12 @@ class DelegatingLoader extends BaseDelegatingLoader { private bool $loading = false; - private array $defaultOptions; - private array $defaultRequirements; - - public function __construct(LoaderResolverInterface $resolver, array $defaultOptions = [], array $defaultRequirements = []) - { - $this->defaultOptions = $defaultOptions; - $this->defaultRequirements = $defaultRequirements; + public function __construct( + LoaderResolverInterface $resolver, + private array $defaultOptions = [], + private array $defaultRequirements = [], + ) { parent::__construct($resolver); } diff --git a/Secrets/DotenvVault.php b/Secrets/DotenvVault.php index 994b31d18..7bdd74c37 100644 --- a/Secrets/DotenvVault.php +++ b/Secrets/DotenvVault.php @@ -16,10 +16,9 @@ */ class DotenvVault extends AbstractVault { - private string $dotenvFile; - - public function __construct(string $dotenvFile) - { + public function __construct( + private string $dotenvFile, + ) { $this->dotenvFile = strtr($dotenvFile, '/', \DIRECTORY_SEPARATOR); } diff --git a/Test/TestBrowserToken.php b/Test/TestBrowserToken.php index 25d71d084..e186b2c44 100644 --- a/Test/TestBrowserToken.php +++ b/Test/TestBrowserToken.php @@ -21,17 +21,16 @@ */ class TestBrowserToken extends AbstractToken { - private string $firewallName; - - public function __construct(array $roles = [], ?UserInterface $user = null, string $firewallName = 'main') - { + public function __construct( + array $roles = [], + ?UserInterface $user = null, + private string $firewallName = 'main', + ) { parent::__construct($roles); if (null !== $user) { $this->setUser($user); } - - $this->firewallName = $firewallName; } public function getFirewallName(): string diff --git a/Translation/Translator.php b/Translation/Translator.php index 1482f0244..870d69ae1 100644 --- a/Translation/Translator.php +++ b/Translation/Translator.php @@ -26,8 +26,6 @@ */ class Translator extends BaseTranslator implements WarmableInterface { - protected ContainerInterface $container; - protected array $loaderIds; protected array $options = [ 'cache_dir' => null, 'debug' => false, @@ -59,11 +57,6 @@ class Translator extends BaseTranslator implements WarmableInterface */ private array $scannedDirectories; - /** - * @var string[] - */ - private array $enabledLocales; - /** * Constructor. * @@ -74,14 +67,18 @@ class Translator extends BaseTranslator implements WarmableInterface * * resource_files: List of translation resources available grouped by locale. * * cache_vary: An array of data that is serialized to generate the cached catalogue name. * + * @param string[] $enabledLocales + * * @throws InvalidArgumentException */ - public function __construct(ContainerInterface $container, MessageFormatterInterface $formatter, string $defaultLocale, array $loaderIds = [], array $options = [], array $enabledLocales = []) - { - $this->container = $container; - $this->loaderIds = $loaderIds; - $this->enabledLocales = $enabledLocales; - + public function __construct( + protected ContainerInterface $container, + MessageFormatterInterface $formatter, + string $defaultLocale, + protected array $loaderIds = [], + array $options = [], + private array $enabledLocales = [], + ) { // check option names if ($diff = array_diff(array_keys($options), array_keys($this->options))) { throw new InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff))); From 6083b478b06abe0be4f6fd1d39db4f33684fc59d Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Tue, 13 Feb 2024 16:18:05 +0100 Subject: [PATCH 064/180] Add new Pushy notifier bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 23f000f90..644403f18 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2804,6 +2804,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ NotifierBridge\PagerDuty\PagerDutyTransportFactory::class => 'notifier.transport_factory.pager-duty', NotifierBridge\Plivo\PlivoTransportFactory::class => 'notifier.transport_factory.plivo', 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index c92d9b4b6..07962a1ed 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -87,6 +87,7 @@ 'ovh-cloud' => Bridge\OvhCloud\OvhCloudTransportFactory::class, 'plivo' => Bridge\Plivo\PlivoTransportFactory::class, 'pushover' => Bridge\Pushover\PushoverTransportFactory::class, + 'pushy' => Bridge\Pushy\PushyTransportFactory::class, 'redlink' => Bridge\Redlink\RedlinkTransportFactory::class, 'ring-central' => Bridge\RingCentral\RingCentralTransportFactory::class, 'sendberry' => Bridge\Sendberry\SendberryTransportFactory::class, From 4e97cadf98ba5188ae097ada3c6f0276040ae293 Mon Sep 17 00:00:00 2001 From: Valentin-Nicusor Barbu Date: Fri, 2 Feb 2024 18:13:46 +0200 Subject: [PATCH 065/180] [Notifier] Add SMSense bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index cf8bb8dfc..444cda2b6 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2759,6 +2759,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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\Telegram\TelegramTransportFactory::class => 'notifier.transport_factory.telegram', NotifierBridge\Telnyx\TelnyxTransportFactory::class => 'notifier.transport_factory.telnyx', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index c92d9b4b6..c1379cd3f 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -100,6 +100,7 @@ 'smsapi' => Bridge\Smsapi\SmsapiTransportFactory::class, 'smsbox' => Bridge\Smsbox\SmsboxTransportFactory::class, 'smsc' => Bridge\Smsc\SmscTransportFactory::class, + 'smsense' => Bridge\Smsense\SmsenseTransportFactory::class, 'smsmode' => Bridge\Smsmode\SmsmodeTransportFactory::class, 'spot-hit' => Bridge\SpotHit\SpotHitTransportFactory::class, 'telnyx' => Bridge\Telnyx\TelnyxTransportFactory::class, From 4f1f39848fa4ca8e05a09b253090fa14b49a6ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 2 Aug 2023 12:30:25 +0200 Subject: [PATCH 066/180] [FrameworkBundle][Workflow] Attach the workflow's configuration to the `workflow` tag --- CHANGELOG.md | 1 + DependencyInjection/FrameworkExtension.php | 2 +- .../FrameworkExtensionTestCase.php | 22 +++++++++++++++---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 950c2b8c5..52624c2cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ CHANGELOG * Add `rate_limiter` tags to rate limiter services * Add `secrets:reveal` command * Add `rate_limiter` option to `http_client.default_options` and `http_client.scoped_clients` + * Attach the workflow's configuration to the `workflow` tag 7.0 --- diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index d2a2afadd..7a52d9f9b 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1029,7 +1029,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $workflowDefinition->replaceArgument(3, $name); $workflowDefinition->replaceArgument(4, $workflow['events_to_dispatch']); - $workflowDefinition->addTag('workflow', ['name' => $name]); + $workflowDefinition->addTag('workflow', ['name' => $name, 'metadata' => $workflow['metadata']]); if ('workflow' === $type) { $workflowDefinition->addTag('workflow.workflow', ['name' => $name]); } elseif ('state_machine' === $type) { diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 7bbbaf2d2..c73197607 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -84,7 +84,6 @@ use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Webhook\Client\RequestParser; use Symfony\Component\Webhook\Controller\WebhookController; -use Symfony\Component\Workflow; use Symfony\Component\Workflow\Exception\InvalidDefinitionException; use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore; use Symfony\Component\Workflow\WorkflowEvents; @@ -302,7 +301,15 @@ public function testWorkflows() $this->assertArrayHasKey('index_4', $args); $this->assertNull($args['index_4'], 'Workflows has eventsToDispatch=null'); - $this->assertSame(['workflow' => [['name' => 'article']], 'workflow.workflow' => [['name' => 'article']]], $container->getDefinition('workflow.article')->getTags()); + $tags = $container->getDefinition('workflow.article')->getTags(); + $this->assertArrayHasKey('workflow', $tags); + $this->assertArrayHasKey('workflow.workflow', $tags); + $this->assertSame([['name' => 'article']], $tags['workflow.workflow']); + $this->assertSame('article', $tags['workflow'][0]['name'] ?? null); + $this->assertSame([ + 'title' => 'article workflow', + 'description' => 'workflow for articles', + ], $tags['workflow'][0]['metadata'] ?? null); $this->assertTrue($container->hasDefinition('workflow.article.definition'), 'Workflow definition is registered as a service'); @@ -333,7 +340,14 @@ public function testWorkflows() $this->assertSame('state_machine.abstract', $container->getDefinition('state_machine.pull_request')->getParent()); $this->assertTrue($container->hasDefinition('state_machine.pull_request.definition'), 'State machine definition is registered as a service'); - $this->assertSame(['workflow' => [['name' => 'pull_request']], 'workflow.state_machine' => [['name' => 'pull_request']]], $container->getDefinition('state_machine.pull_request')->getTags()); + $tags = $container->getDefinition('state_machine.pull_request')->getTags(); + $this->assertArrayHasKey('workflow', $tags); + $this->assertArrayHasKey('workflow.state_machine', $tags); + $this->assertSame([['name' => 'pull_request']], $tags['workflow.state_machine']); + $this->assertSame('pull_request', $tags['workflow'][0]['name'] ?? null); + $this->assertSame([ + 'title' => 'workflow title', + ], $tags['workflow'][0]['metadata'] ?? null); $stateMachineDefinition = $container->getDefinition('state_machine.pull_request.definition'); @@ -357,7 +371,7 @@ public function testWorkflows() $this->assertSame('state_machine.pull_request.metadata_store', (string) $metadataStoreReference); $metadataStoreDefinition = $container->getDefinition('state_machine.pull_request.metadata_store'); - $this->assertSame(Workflow\Metadata\InMemoryMetadataStore::class, $metadataStoreDefinition->getClass()); + $this->assertSame(InMemoryMetadataStore::class, $metadataStoreDefinition->getClass()); $this->assertSame(InMemoryMetadataStore::class, $metadataStoreDefinition->getClass()); $workflowMetadata = $metadataStoreDefinition->getArgument(0); From 12901443fc62e4a4e23dfe398ee4b86755e7c22c Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 6 Mar 2024 11:55:15 +0100 Subject: [PATCH 067/180] [Filesystem] Add the readFile() method --- Command/AssetsInstallCommand.php | 2 +- Command/CacheClearCommand.php | 2 +- DependencyInjection/FrameworkExtension.php | 3 ++- .../CacheClearCommand/CacheClearCommandTest.php | 4 ++-- Tests/Secrets/SodiumVaultTest.php | 10 ++++++---- composer.json | 2 +- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Command/AssetsInstallCommand.php b/Command/AssetsInstallCommand.php index cb05fe827..32b38de9a 100644 --- a/Command/AssetsInstallCommand.php +++ b/Command/AssetsInstallCommand.php @@ -260,7 +260,7 @@ private function getPublicDirectory(ContainerInterface $container): string return $defaultPublicDir; } - $composerConfig = json_decode(file_get_contents($composerFilePath), true); + $composerConfig = json_decode($this->filesystem->readFile($composerFilePath), true, flags: \JSON_THROW_ON_ERROR); return $composerConfig['extra']['public-dir'] ?? $defaultPublicDir; } diff --git a/Command/CacheClearCommand.php b/Command/CacheClearCommand.php index 8a1dedd27..4122db6fd 100644 --- a/Command/CacheClearCommand.php +++ b/Command/CacheClearCommand.php @@ -232,7 +232,7 @@ private function warmup(string $warmupDir, string $realBuildDir): void $search = [$warmupDir, str_replace('\\', '\\\\', $warmupDir)]; $replace = str_replace('\\', '/', $realBuildDir); foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file), $count); + $content = str_replace($search, $replace, $this->filesystem->readFile($file), $count); if ($count) { file_put_contents($file, $content); } diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 7a52d9f9b..911242bc2 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -71,6 +71,7 @@ use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Glob; use Symfony\Component\Form\Extension\HtmlSanitizer\Type\TextTypeHtmlSanitizerExtension; @@ -3141,7 +3142,7 @@ private function getPublicDirectory(ContainerBuilder $container): string } $container->addResource(new FileResource($composerFilePath)); - $composerConfig = json_decode(file_get_contents($composerFilePath), true); + $composerConfig = json_decode((new Filesystem())->readFile($composerFilePath), true, flags: \JSON_THROW_ON_ERROR); return isset($composerConfig['extra']['public-dir']) ? $projectDir.'/'.$composerConfig['extra']['public-dir'] : $defaultPublicDir; } diff --git a/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index 78b13905e..b950b5fd9 100644 --- a/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -75,7 +75,7 @@ function () use ($file) { $kernelRef = new \ReflectionObject($this->kernel); $kernelFile = $kernelRef->getFileName(); /** @var ResourceInterface[] $meta */ - $meta = unserialize(file_get_contents($containerMetaFile)); + $meta = unserialize($this->fs->readFile($containerMetaFile)); $found = false; foreach ($meta as $resource) { if ((string) $resource === $kernelFile) { @@ -93,7 +93,7 @@ function () use ($file) { ); $this->assertMatchesRegularExpression( sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', $containerClass), - file_get_contents($containerFile), + $this->fs->readFile($containerFile), 'kernel.container_class is properly set on the dumped container' ); } diff --git a/Tests/Secrets/SodiumVaultTest.php b/Tests/Secrets/SodiumVaultTest.php index 603d13504..96d5dcea1 100644 --- a/Tests/Secrets/SodiumVaultTest.php +++ b/Tests/Secrets/SodiumVaultTest.php @@ -21,16 +21,18 @@ class SodiumVaultTest extends TestCase { private string $secretsDir; + private Filesystem $filesystem; protected function setUp(): void { + $this->filesystem = new Filesystem(); $this->secretsDir = sys_get_temp_dir().'/sf_secrets/test/'; - (new Filesystem())->remove($this->secretsDir); + $this->filesystem->remove($this->secretsDir); } protected function tearDown(): void { - (new Filesystem())->remove($this->secretsDir); + $this->filesystem->remove($this->secretsDir); } public function testGenerateKeys() @@ -41,8 +43,8 @@ public function testGenerateKeys() $this->assertFileExists($this->secretsDir.'/test.encrypt.public.php'); $this->assertFileExists($this->secretsDir.'/test.decrypt.private.php'); - $encKey = file_get_contents($this->secretsDir.'/test.encrypt.public.php'); - $decKey = file_get_contents($this->secretsDir.'/test.decrypt.private.php'); + $encKey = $this->filesystem->readFile($this->secretsDir.'/test.encrypt.public.php'); + $decKey = $this->filesystem->readFile($this->secretsDir.'/test.decrypt.private.php'); $this->assertFalse($vault->generateKeys()); $this->assertStringEqualsFile($this->secretsDir.'/test.encrypt.public.php', $encKey); diff --git a/composer.json b/composer.json index 7b9d1b3e5..4d66cf9bc 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "symfony/http-foundation": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "^6.4|^7.0", + "symfony/filesystem": "^7.1", "symfony/finder": "^6.4|^7.0", "symfony/routing": "^6.4|^7.0" }, From facab7ae1656d3217684dbbfc3ee4ee78f787229 Mon Sep 17 00:00:00 2001 From: Nicolas Appriou Date: Wed, 1 Feb 2023 11:54:16 +0100 Subject: [PATCH 068/180] [FrameworkBundle][HttpFoundation] reduce response constraints verbosity --- Test/BrowserKitAssertionsTrait.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Test/BrowserKitAssertionsTrait.php b/Test/BrowserKitAssertionsTrait.php index 125aa45a7..7eea648cb 100644 --- a/Test/BrowserKitAssertionsTrait.php +++ b/Test/BrowserKitAssertionsTrait.php @@ -28,14 +28,14 @@ */ trait BrowserKitAssertionsTrait { - public static function assertResponseIsSuccessful(string $message = ''): void + public static function assertResponseIsSuccessful(string $message = '', bool $verbose = true): void { - self::assertThatForResponse(new ResponseConstraint\ResponseIsSuccessful(), $message); + self::assertThatForResponse(new ResponseConstraint\ResponseIsSuccessful($verbose), $message); } - public static function assertResponseStatusCodeSame(int $expectedCode, string $message = ''): void + public static function assertResponseStatusCodeSame(int $expectedCode, string $message = '', bool $verbose = true): void { - self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message); + self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode, $verbose), $message); } public static function assertResponseFormatSame(?string $expectedFormat, string $message = ''): void @@ -43,9 +43,9 @@ public static function assertResponseFormatSame(?string $expectedFormat, string self::assertThatForResponse(new ResponseConstraint\ResponseFormatSame(self::getRequest(), $expectedFormat), $message); } - public static function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = ''): void + public static function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = '', bool $verbose = true): void { - $constraint = new ResponseConstraint\ResponseIsRedirected(); + $constraint = new ResponseConstraint\ResponseIsRedirected($verbose); if ($expectedLocation) { if (class_exists(ResponseConstraint\ResponseHeaderLocationSame::class)) { $locationConstraint = new ResponseConstraint\ResponseHeaderLocationSame(self::getRequest(), $expectedLocation); @@ -100,9 +100,9 @@ public static function assertResponseCookieValueSame(string $name, string $expec ), $message); } - public static function assertResponseIsUnprocessable(string $message = ''): void + public static function assertResponseIsUnprocessable(string $message = '', bool $verbose = true): void { - self::assertThatForResponse(new ResponseConstraint\ResponseIsUnprocessable(), $message); + self::assertThatForResponse(new ResponseConstraint\ResponseIsUnprocessable($verbose), $message); } public static function assertBrowserHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void From 000203b325e8df22412c03d3e3f5d28f2d12be08 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Mon, 18 Mar 2024 20:27:13 +0100 Subject: [PATCH 069/180] chore: CS fixes --- Test/DomCrawlerAssertionsTrait.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Test/DomCrawlerAssertionsTrait.php b/Test/DomCrawlerAssertionsTrait.php index a16709461..024c78f75 100644 --- a/Test/DomCrawlerAssertionsTrait.php +++ b/Test/DomCrawlerAssertionsTrait.php @@ -26,12 +26,12 @@ trait DomCrawlerAssertionsTrait { public static function assertSelectorExists(string $selector, string $message = ''): void { - self::assertThat(self::getCrawler(), new DomCrawlerConstraint\CrawlerSelectorExists($selector), $message); + self::assertThat(self::getCrawler(), new CrawlerSelectorExists($selector), $message); } public static function assertSelectorNotExists(string $selector, string $message = ''): void { - self::assertThat(self::getCrawler(), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorExists($selector)), $message); + self::assertThat(self::getCrawler(), new LogicalNot(new CrawlerSelectorExists($selector)), $message); } public static function assertSelectorCount(int $expectedCount, string $selector, string $message = ''): void @@ -42,7 +42,7 @@ public static function assertSelectorCount(int $expectedCount, string $selector, public static function assertSelectorTextContains(string $selector, string $text, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text) ), $message); } @@ -50,7 +50,7 @@ public static function assertSelectorTextContains(string $selector, string $text public static function assertAnySelectorTextContains(string $selector, string $text, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerAnySelectorTextContains($selector, $text) ), $message); } @@ -58,7 +58,7 @@ public static function assertAnySelectorTextContains(string $selector, string $t public static function assertSelectorTextSame(string $selector, string $text, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerSelectorTextSame($selector, $text) ), $message); } @@ -66,7 +66,7 @@ public static function assertSelectorTextSame(string $selector, string $text, st public static function assertAnySelectorTextSame(string $selector, string $text, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new CrawlerSelectorExists($selector), new DomCrawlerConstraint\CrawlerAnySelectorTextSame($selector, $text) ), $message); } @@ -74,7 +74,7 @@ public static function assertAnySelectorTextSame(string $selector, string $text, public static function assertSelectorTextNotContains(string $selector, string $text, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new CrawlerSelectorExists($selector), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text)) ), $message); } @@ -82,7 +82,7 @@ public static function assertSelectorTextNotContains(string $selector, string $t public static function assertAnySelectorTextNotContains(string $selector, string $text, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new CrawlerSelectorExists($selector), new LogicalNot(new DomCrawlerConstraint\CrawlerAnySelectorTextContains($selector, $text)) ), $message); } @@ -100,7 +100,7 @@ public static function assertPageTitleContains(string $expectedTitle, string $me public static function assertInputValueSame(string $fieldName, string $expectedValue, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists("input[name=\"$fieldName\"]"), + new CrawlerSelectorExists("input[name=\"$fieldName\"]"), new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue) ), $message); } @@ -108,7 +108,7 @@ public static function assertInputValueSame(string $fieldName, string $expectedV public static function assertInputValueNotSame(string $fieldName, string $expectedValue, string $message = ''): void { self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists("input[name=\"$fieldName\"]"), + new CrawlerSelectorExists("input[name=\"$fieldName\"]"), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue)) ), $message); } From 911ba6ce0126245dce935cf713d120db63228911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 21 Mar 2024 11:47:10 +0100 Subject: [PATCH 070/180] [DependencyInjection] Apply attribute configurator to child classes --- DependencyInjection/FrameworkExtension.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 911242bc2..7d584af8b 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -699,9 +699,9 @@ public function load(array $configs, ContainerBuilder $container): void $taskAttributeClass, static function (ChildDefinition $definition, AsPeriodicTask|AsCronTask $attribute, \ReflectionClass|\ReflectionMethod $reflector): void { $tagAttributes = get_object_vars($attribute) + [ - 'trigger' => match ($attribute::class) { - AsPeriodicTask::class => 'every', - AsCronTask::class => 'cron', + 'trigger' => match (true) { + $attribute instanceof AsPeriodicTask => 'every', + $attribute instanceof AsCronTask => 'cron', }, ]; if ($reflector instanceof \ReflectionMethod) { From 05ed395cc169aa68a1ea8dca02508195a4861a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Sat, 23 Mar 2024 11:52:11 +0100 Subject: [PATCH 071/180] Remove custom handler for Workflow listener attributes --- DependencyInjection/FrameworkExtension.php | 23 ---------------------- composer.json | 2 +- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 7d584af8b..1fd7881f3 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1104,29 +1104,6 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $container->setParameter('workflow.has_guard_listeners', true); } } - - $listenerAttributes = [ - Workflow\Attribute\AsAnnounceListener::class, - Workflow\Attribute\AsCompletedListener::class, - Workflow\Attribute\AsEnterListener::class, - Workflow\Attribute\AsEnteredListener::class, - Workflow\Attribute\AsGuardListener::class, - Workflow\Attribute\AsLeaveListener::class, - Workflow\Attribute\AsTransitionListener::class, - ]; - - foreach ($listenerAttributes as $attribute) { - $container->registerAttributeForAutoconfiguration($attribute, static function (ChildDefinition $definition, AsEventListener $attribute, \ReflectionClass|\ReflectionMethod $reflector) { - $tagAttributes = get_object_vars($attribute); - if ($reflector instanceof \ReflectionMethod) { - if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('"%s" attribute cannot declare a method on "%s::%s()".', $attribute::class, $reflector->class, $reflector->name)); - } - $tagAttributes['method'] = $reflector->getName(); - } - $definition->addTag('kernel.event_listener', $tagAttributes); - }); - } } private function registerDebugConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void diff --git a/composer.json b/composer.json index 4d66cf9bc..af934f35d 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "ext-xml": "*", "symfony/cache": "^6.4|^7.0", "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^7.1", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", "symfony/event-dispatcher": "^6.4|^7.0", From a39bf97648316cef7379aff34e5b6a86d00d2559 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 24 Mar 2024 21:56:27 +0100 Subject: [PATCH 072/180] [Security] Support multiple signature algorithms and JWK/JWKSet for OIDC tokens --- DependencyInjection/Compiler/UnusedTagsPass.php | 1 + 1 file changed, 1 insertion(+) diff --git a/DependencyInjection/Compiler/UnusedTagsPass.php b/DependencyInjection/Compiler/UnusedTagsPass.php index 6f53e57f0..a2a141afb 100644 --- a/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/DependencyInjection/Compiler/UnusedTagsPass.php @@ -82,6 +82,7 @@ class UnusedTagsPass implements CompilerPassInterface 'routing.route_loader', 'scheduler.schedule_provider', 'scheduler.task', + 'security.access_token_handler.oidc.signature_algorithm', 'security.authenticator.login_linker', 'security.expression_language_provider', 'security.remember_me_handler', From 03c2c663a821df3881a1b2cc9e6ad6ab8a3951d1 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Thu, 26 Oct 2023 10:56:04 +0200 Subject: [PATCH 073/180] [PropertyInfo] Deprecate PropertyInfo Type Co-authored-by: Baptiste Leduc --- Tests/Functional/PropertyInfoTest.php | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/Tests/Functional/PropertyInfoTest.php b/Tests/Functional/PropertyInfoTest.php index c61955d37..18cd61b08 100644 --- a/Tests/Functional/PropertyInfoTest.php +++ b/Tests/Functional/PropertyInfoTest.php @@ -11,7 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; -use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\PropertyInfo\Type as LegacyType; +use Symfony\Component\TypeInfo\Type; class PropertyInfoTest extends AbstractWebTestCase { @@ -19,7 +20,29 @@ public function testPhpDocPriority() { static::bootKernel(['test_case' => 'Serializer']); - $this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))], static::getContainer()->get('property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes')); + $propertyInfo = static::getContainer()->get('property_info'); + + if (!method_exists($propertyInfo, 'getType')) { + $this->markTestSkipped(); + } + + $this->assertEquals(Type::list(Type::int()), $propertyInfo->getType(Dummy::class, 'codes')); + } + + /** + * @group legacy + */ + public function testPhpDocPriorityLegacy() + { + static::bootKernel(['test_case' => 'Serializer']); + + $propertyInfo = static::getContainer()->get('property_info'); + + if (!method_exists($propertyInfo, 'getTypes')) { + $this->markTestSkipped(); + } + + $this->assertEquals([new LegacyType('array', false, null, true, new LegacyType('int'), new LegacyType('int'))], $propertyInfo->getTypes(Dummy::class, 'codes')); } } From bc336a14228dbe02d49a51a0199abc2684955366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 23 Feb 2024 16:46:28 +0100 Subject: [PATCH 074/180] [Mailer] Add support for allowing some users even if `recipients` is defined in `EnvelopeListener` --- CHANGELOG.md | 2 ++ DependencyInjection/Configuration.php | 13 ++++++++++++- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/schema/symfony-1.0.xsd | 1 + .../Fixtures/php/mailer_with_dsn.php | 1 + .../Fixtures/php/mailer_with_transports.php | 1 + .../Fixtures/xml/mailer_with_dsn.xml | 1 + .../Fixtures/xml/mailer_with_transports.xml | 2 ++ .../Fixtures/yml/mailer_with_dsn.yml | 2 ++ .../Fixtures/yml/mailer_with_transports.yml | 3 +++ .../FrameworkExtensionTestCase.php | 5 ++++- 11 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52624c2cd..df0d692eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ CHANGELOG * Add `secrets:reveal` command * Add `rate_limiter` option to `http_client.default_options` and `http_client.scoped_clients` * Attach the workflow's configuration to the `workflow` tag + * Add the `allowed_recipients` option for mailer to allow some users to receive + emails even if `recipients` is defined. 7.0 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 8d54f74ef..92c20d139 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -2117,12 +2117,23 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl ->arrayNode('envelope') ->info('Mailer Envelope configuration') ->fixXmlConfig('recipient') + ->fixXmlConfig('allowed_recipient') ->children() ->scalarNode('sender')->end() ->arrayNode('recipients') ->performNoDeepMerging() ->beforeNormalization() - ->ifArray() + ->ifArray() + ->then(fn ($v) => array_filter(array_values($v))) + ->end() + ->prototype('scalar')->end() + ->end() + ->arrayNode('allowed_recipients') + ->info('A list of regular expressions that allow recipients when "recipients" option is defined.') + ->example(['.*@example\.com']) + ->performNoDeepMerging() + ->beforeNormalization() + ->ifArray() ->then(fn ($v) => array_filter(array_values($v))) ->end() ->prototype('scalar')->end() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 1fd7881f3..86355e5ca 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2647,6 +2647,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co $envelopeListener = $container->getDefinition('mailer.envelope_listener'); $envelopeListener->setArgument(0, $config['envelope']['sender'] ?? null); $envelopeListener->setArgument(1, $config['envelope']['recipients'] ?? null); + $envelopeListener->setArgument(2, $config['envelope']['allowed_recipients'] ?? []); if ($config['headers']) { $headers = new Definition(Headers::class); diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index ad02ec370..d8d23168d 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -764,6 +764,7 @@ + diff --git a/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php b/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php index 683872982..3357bf354 100644 --- a/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php +++ b/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php @@ -13,6 +13,7 @@ 'envelope' => [ 'sender' => 'sender@example.org', 'recipients' => ['redirected@example.org'], + 'allowed_recipients' => ['foobar@example\.org'], ], 'headers' => [ 'from' => 'from@example.org', diff --git a/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php b/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php index 361fe731c..e51fd056b 100644 --- a/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php +++ b/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php @@ -16,6 +16,7 @@ 'envelope' => [ 'sender' => 'sender@example.org', 'recipients' => ['redirected@example.org', 'redirected1@example.org'], + 'allowed_recipients' => ['foobar@example\.org', '.*@example\.com'], ], 'headers' => [ 'from' => 'from@example.org', diff --git a/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml b/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml index 3436cf417..d48b7423a 100644 --- a/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml +++ b/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml @@ -13,6 +13,7 @@ sender@example.org redirected@example.org + foobar@example\.org from@example.org bcc1@example.org diff --git a/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml b/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml index 1cd8523b6..9bfd18d91 100644 --- a/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml +++ b/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml @@ -16,6 +16,8 @@ sender@example.org redirected@example.org redirected1@example.org + foobar@example\.org + .*@example\.com from@example.org bcc1@example.org diff --git a/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml b/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml index e826d6bdc..ea703bdad 100644 --- a/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml +++ b/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml @@ -10,6 +10,8 @@ framework: sender: sender@example.org recipients: - redirected@example.org + allowed_recipients: + - foobar@example\.org headers: from: from@example.org bcc: [bcc1@example.org, bcc2@example.org] diff --git a/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml b/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml index 59a5f14fd..ae10f6aee 100644 --- a/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml +++ b/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml @@ -13,6 +13,9 @@ framework: recipients: - redirected@example.org - redirected1@example.org + allowed_recipients: + - foobar@example\.org + - .*@example\.com headers: from: from@example.org bcc: [bcc1@example.org, bcc2@example.org] diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index dd836c06f..2a26e786b 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -2043,6 +2043,7 @@ public static function provideMailer(): iterable 'mailer_with_dsn', ['main' => 'smtp://example.com'], ['redirected@example.org'], + ['foobar@example\.org'], ]; yield [ 'mailer_with_transports', @@ -2051,13 +2052,14 @@ public static function provideMailer(): iterable 'transport2' => 'smtp://example2.com', ], ['redirected@example.org', 'redirected1@example.org'], + ['foobar@example\.org', '.*@example\.com'], ]; } /** * @dataProvider provideMailer */ - public function testMailer(string $configFile, array $expectedTransports, array $expectedRecipients) + public function testMailer(string $configFile, array $expectedTransports, array $expectedRecipients, array $expectedAllowedRecipients) { $container = $this->createContainerFromFile($configFile); @@ -2070,6 +2072,7 @@ public function testMailer(string $configFile, array $expectedTransports, array $l = $container->getDefinition('mailer.envelope_listener'); $this->assertSame('sender@example.org', $l->getArgument(0)); $this->assertSame($expectedRecipients, $l->getArgument(1)); + $this->assertSame($expectedAllowedRecipients, $l->getArgument(2)); $this->assertEquals(new Reference('messenger.default_bus', ContainerInterface::NULL_ON_INVALID_REFERENCE), $container->getDefinition('mailer.mailer')->getArgument(1)); $this->assertTrue($container->hasDefinition('mailer.message_listener')); From 1bda227a3a8482d2f3496a2e454b639d92846973 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 13 Apr 2024 09:53:50 +0200 Subject: [PATCH 075/180] forward a Clock instance to the created InMemoryTransport --- Resources/config/messenger.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Resources/config/messenger.php b/Resources/config/messenger.php index f71fcf344..df2476096 100644 --- a/Resources/config/messenger.php +++ b/Resources/config/messenger.php @@ -135,6 +135,9 @@ ->tag('messenger.transport_factory') ->set('messenger.transport.in_memory.factory', InMemoryTransportFactory::class) + ->args([ + service('clock')->nullOnInvalid(), + ]) ->tag('messenger.transport_factory') ->tag('kernel.reset', ['method' => 'reset']) From 68faa46eeb25f7e04fdbf38ee21444d23662cfce Mon Sep 17 00:00:00 2001 From: Andrey Lebedev Date: Wed, 20 Mar 2024 19:51:25 +0400 Subject: [PATCH 076/180] [Notifier] LOX24 SMS bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 911242bc2..74a1c71ea 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2788,6 +2788,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ NotifierBridge\LightSms\LightSmsTransportFactory::class => 'notifier.transport_factory.light-sms', 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\Mattermost\MattermostTransportFactory::class => 'notifier.transport_factory.mattermost', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index cebb92350..df9be94ed 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -75,6 +75,7 @@ 'isendpro' => Bridge\Isendpro\IsendproTransportFactory::class, 'kaz-info-teh' => Bridge\KazInfoTeh\KazInfoTehTransportFactory::class, 'light-sms' => Bridge\LightSms\LightSmsTransportFactory::class, + 'lox24' => Bridge\Lox24\Lox24TransportFactory::class, 'mailjet' => Bridge\Mailjet\MailjetTransportFactory::class, 'message-bird' => Bridge\MessageBird\MessageBirdTransportFactory::class, 'message-media' => Bridge\MessageMedia\MessageMediaTransportFactory::class, From 8db28484a473acc4aab94cf349ae139921226391 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 19 Apr 2024 20:47:43 +0200 Subject: [PATCH 077/180] [FrameworkBundle] Add support for setting `headers` with `TemplateController` --- CHANGELOG.md | 5 +++++ Controller/TemplateController.php | 7 ++++++- Tests/Controller/TemplateControllerTest.php | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df0d692eb..75ffef1a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.2 +--- + + * Add support for setting `headers` with `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` + 7.1 --- diff --git a/Controller/TemplateController.php b/Controller/TemplateController.php index bcbcc382d..125e04f62 100644 --- a/Controller/TemplateController.php +++ b/Controller/TemplateController.php @@ -37,8 +37,9 @@ public function __construct( * @param bool|null $private Whether or not caching should apply for client caches only * @param array $context The context (arguments) of the template * @param int $statusCode The HTTP status code to return with the response (200 "OK" by default) + * @param array $headers The HTTP headers to add to the response */ - public function templateAction(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200): Response + public function templateAction(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200, array $headers = []): Response { if (null === $this->twig) { throw new \LogicException('You cannot use the TemplateController if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); @@ -60,6 +61,10 @@ public function templateAction(string $template, ?int $maxAge = null, ?int $shar $response->setPublic(); } + foreach ($headers as $key => $value) { + $response->headers->set($key, $value); + } + return $response; } diff --git a/Tests/Controller/TemplateControllerTest.php b/Tests/Controller/TemplateControllerTest.php index c972151d2..28f63ac01 100644 --- a/Tests/Controller/TemplateControllerTest.php +++ b/Tests/Controller/TemplateControllerTest.php @@ -84,4 +84,18 @@ public function testStatusCode() $this->assertSame(201, $controller->templateAction($templateName, null, null, null, [], $statusCode)->getStatusCode()); $this->assertSame(200, $controller->templateAction($templateName)->getStatusCode()); } + + public function testHeaders() + { + $templateName = 'image.svg.twig'; + + $loader = new ArrayLoader(); + $loader->setTemplate($templateName, ''); + + $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->assertNull($controller->templateAction($templateName)->headers->get('Content-Type')); + } } From 766daee94c7fa35637c85eb4e8e77acd2bfea49b Mon Sep 17 00:00:00 2001 From: Samael tomas Date: Fri, 26 Apr 2024 14:48:25 +0200 Subject: [PATCH 078/180] [Notifier] Add Primotexto bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index d293ae9f4..039dda9d5 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2783,6 +2783,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index df9be94ed..078adb960 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -87,6 +87,7 @@ 'orange-sms' => Bridge\OrangeSms\OrangeSmsTransportFactory::class, 'ovh-cloud' => Bridge\OvhCloud\OvhCloudTransportFactory::class, 'plivo' => Bridge\Plivo\PlivoTransportFactory::class, + 'primotexto' => Bridge\Primotexto\PrimotextoTransportFactory::class, 'pushover' => Bridge\Pushover\PushoverTransportFactory::class, 'pushy' => Bridge\Pushy\PushyTransportFactory::class, 'redlink' => Bridge\Redlink\RedlinkTransportFactory::class, From e8cba2142d7a62bae0b96c1f6cb20e4ad39dc864 Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Thu, 18 Apr 2024 18:37:37 +0200 Subject: [PATCH 079/180] [DependencyInjection] Reset env vars when resetting the container --- CHANGELOG.md | 1 + Resources/config/secrets.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df0d692eb..4b0475167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ CHANGELOG * Attach the workflow's configuration to the `workflow` tag * Add the `allowed_recipients` option for mailer to allow some users to receive emails even if `recipients` is defined. + * Reset env vars when resetting the container 7.0 --- diff --git a/Resources/config/secrets.php b/Resources/config/secrets.php index a21d28270..8192f2f06 100644 --- a/Resources/config/secrets.php +++ b/Resources/config/secrets.php @@ -13,6 +13,7 @@ use Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault; use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; +use Symfony\Component\DependencyInjection\StaticEnvVarLoader; return static function (ContainerConfigurator $container) { $container->services() @@ -21,6 +22,9 @@ abstract_arg('Secret dir, set in FrameworkExtension'), service('secrets.decryption_key')->ignoreOnInvalid(), ]) + + ->set('secrets.env_var_loader', StaticEnvVarLoader::class) + ->args([service('secrets.vault')]) ->tag('container.env_var_loader') ->set('secrets.decryption_key') From 59f4fb50d93f4526f49ab30a9b7fde7df7ab9ced Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 22 May 2024 17:24:31 +0200 Subject: [PATCH 080/180] [FrameworkBundle] Derivate kernel.secret from the decryption secret when its env var is not defined --- CHANGELOG.md | 1 + DependencyInjection/FrameworkExtension.php | 7 +++++-- Resources/config/secrets.php | 1 + Secrets/SodiumVault.php | 9 ++++++++- Tests/Secrets/SodiumVaultTest.php | 9 +++++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8309ce3e1..370786e61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add support for setting `headers` with `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` + * Derivate `kernel.secret` from the decryption secret when its env var is not defined 7.1 --- diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 8786d04bd..5586e6653 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -372,7 +372,7 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerDebugConfiguration($config['php_errors'], $container, $loader); $this->registerRouterConfiguration($config['router'], $container, $loader, $config['enabled_locales']); $this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader); - $this->registerSecretsConfiguration($config['secrets'], $container, $loader); + $this->registerSecretsConfiguration($config['secrets'], $container, $loader, $config['secret'] ?? null); $container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']); @@ -1755,7 +1755,7 @@ private function registerPropertyAccessConfiguration(array $config, ContainerBui ; } - private function registerSecretsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void + private function registerSecretsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, ?string $secret): void { if (!$this->readConfigEnabled('secrets', $container, $config)) { $container->removeDefinition('console.command.secrets_set'); @@ -1771,6 +1771,9 @@ private function registerSecretsConfiguration(array $config, ContainerBuilder $c $loader->load('secrets.php'); + $container->resolveEnvPlaceholders($secret, null, $usedEnvs); + $secretEnvVar = 1 === \count($usedEnvs ?? []) ? substr(key($usedEnvs), 1 + (strrpos(key($usedEnvs), ':') ?: -1)) : null; + $container->getDefinition('secrets.vault')->replaceArgument(2, $secretEnvVar); $container->getDefinition('secrets.vault')->replaceArgument(0, $config['vault_directory']); if ($config['local_dotenv_file']) { diff --git a/Resources/config/secrets.php b/Resources/config/secrets.php index 8192f2f06..a82f397b8 100644 --- a/Resources/config/secrets.php +++ b/Resources/config/secrets.php @@ -21,6 +21,7 @@ ->args([ abstract_arg('Secret dir, set in FrameworkExtension'), service('secrets.decryption_key')->ignoreOnInvalid(), + abstract_arg('Secret env var, set in FrameworkExtension'), ]) ->set('secrets.env_var_loader', StaticEnvVarLoader::class) diff --git a/Secrets/SodiumVault.php b/Secrets/SodiumVault.php index dcf79869f..f09c3b3af 100644 --- a/Secrets/SodiumVault.php +++ b/Secrets/SodiumVault.php @@ -26,16 +26,18 @@ class SodiumVault extends AbstractVault implements EnvVarLoaderInterface private string|\Stringable|null $decryptionKey = null; private string $pathPrefix; private ?string $secretsDir; + private ?string $derivedSecretEnvVar; /** * @param $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault * or null to store generated keys in the provided $secretsDir */ - public function __construct(string $secretsDir, #[\SensitiveParameter] string|\Stringable|null $decryptionKey = null) + public function __construct(string $secretsDir, #[\SensitiveParameter] string|\Stringable|null $decryptionKey = null, ?string $derivedSecretEnvVar = null) { $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.basename($secretsDir).'.'; $this->decryptionKey = $decryptionKey; $this->secretsDir = $secretsDir; + $this->derivedSecretEnvVar = $derivedSecretEnvVar; } public function generateKeys(bool $override = false): bool @@ -177,6 +179,11 @@ public function loadEnvVars(): array $envs[$name] = LazyString::fromCallable($reveal, $name); } + if ($this->derivedSecretEnvVar && !\array_key_exists($this->derivedSecretEnvVar, $envs)) { + $decryptionKey = $this->decryptionKey; + $envs[$this->derivedSecretEnvVar] = LazyString::fromCallable(static fn () => base64_encode(hash('sha256', $decryptionKey, true))); + } + return $envs; } diff --git a/Tests/Secrets/SodiumVaultTest.php b/Tests/Secrets/SodiumVaultTest.php index 96d5dcea1..e31e8364f 100644 --- a/Tests/Secrets/SodiumVaultTest.php +++ b/Tests/Secrets/SodiumVaultTest.php @@ -75,4 +75,13 @@ public function testEncryptAndDecrypt() $this->assertSame([], $vault->list()); } + + public function testDerivedSecretEnvVar() + { + $vault = new SodiumVault($this->secretsDir, null, 'MY_SECRET'); + $vault->generateKeys(); + $vault->seal('FOO', 'bar'); + + $this->assertSame(['FOO', 'MY_SECRET'], array_keys($vault->loadEnvVars())); + } } From 029743710a18f7bd47db7843d6aaf2788f0dc84f Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Thu, 23 May 2024 13:24:31 +0200 Subject: [PATCH 081/180] Do not require `http_client` service This makes it possible to use AssetMapper with `http_client` disabled on the framework. Example: ```php $configurator->extension( 'framework', [ 'http_client' => [ 'enabled' => false, ], 'asset_mapper' => [ 'paths' => [ 'assets/', ], ], ] ); ``` --- Resources/config/asset_mapper.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/config/asset_mapper.php b/Resources/config/asset_mapper.php index b7ce65f03..ae7039db2 100644 --- a/Resources/config/asset_mapper.php +++ b/Resources/config/asset_mapper.php @@ -197,7 +197,7 @@ ]) ->set('asset_mapper.importmap.resolver', JsDelivrEsmResolver::class) - ->args([service('http_client')]) + ->args([service('http_client')->nullOnInvalid()]) ->set('asset_mapper.importmap.renderer', ImportMapRenderer::class) ->args([ @@ -212,12 +212,12 @@ ->set('asset_mapper.importmap.auditor', ImportMapAuditor::class) ->args([ service('asset_mapper.importmap.config_reader'), - service('http_client'), + service('http_client')->nullOnInvalid(), ]) ->set('asset_mapper.importmap.update_checker', ImportMapUpdateChecker::class) ->args([ service('asset_mapper.importmap.config_reader'), - service('http_client'), + service('http_client')->nullOnInvalid(), ]) ->set('asset_mapper.importmap.command.require', ImportMapRequireCommand::class) From e180d81181fd3bc0320180b4e05ba48b48771769 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 11 Apr 2024 18:13:33 +0200 Subject: [PATCH 082/180] [Translator] Add lint:translations command --- DependencyInjection/FrameworkExtension.php | 6 ++++++ Resources/config/console.php | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 5586e6653..b5f325ff3 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -165,6 +165,7 @@ use Symfony\Component\String\LazyString; use Symfony\Component\String\Slugger\SluggerInterface; use Symfony\Component\Translation\Bridge as TranslationBridge; +use Symfony\Component\Translation\Command\TranslationLintCommand as BaseTranslationLintCommand; use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; use Symfony\Component\Translation\Extractor\PhpAstExtractor; use Symfony\Component\Translation\LocaleSwitcher; @@ -245,6 +246,10 @@ public function load(array $configs, ContainerBuilder $container): void $container->removeDefinition('console.command.yaml_lint'); } + if (!class_exists(BaseTranslationLintCommand::class)) { + $container->removeDefinition('console.command.translation_lint'); + } + if (!class_exists(DebugCommand::class)) { $container->removeDefinition('console.command.dotenv_debug'); } @@ -1413,6 +1418,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $container->removeDefinition('console.command.translation_extract'); $container->removeDefinition('console.command.translation_pull'); $container->removeDefinition('console.command.translation_push'); + $container->removeDefinition('console.command.translation_lint'); return; } diff --git a/Resources/config/console.php b/Resources/config/console.php index b4f7dfcf3..9df82e20e 100644 --- a/Resources/config/console.php +++ b/Resources/config/console.php @@ -54,6 +54,7 @@ use Symfony\Component\Messenger\Command\StopWorkersCommand; use Symfony\Component\Scheduler\Command\DebugCommand as SchedulerDebugCommand; use Symfony\Component\Serializer\Command\DebugCommand as SerializerDebugCommand; +use Symfony\Component\Translation\Command\TranslationLintCommand; use Symfony\Component\Translation\Command\TranslationPullCommand; use Symfony\Component\Translation\Command\TranslationPushCommand; use Symfony\Component\Translation\Command\XliffLintCommand; @@ -317,6 +318,13 @@ ->set('console.command.yaml_lint', YamlLintCommand::class) ->tag('console.command') + ->set('console.command.translation_lint', TranslationLintCommand::class) + ->args([ + service('translator'), + param('kernel.enabled_locales'), + ]) + ->tag('console.command') + ->set('console.command.form_debug', \Symfony\Component\Form\Command\DebugCommand::class) ->args([ service('form.registry'), From 408da06829094b30d891e26271502d03e35658ca Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 7 Jun 2024 13:36:04 +0200 Subject: [PATCH 083/180] change notifier type for brevo from chatter to texter --- Resources/config/notifier_transports.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index df9be94ed..5ddc9ae24 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -27,7 +27,6 @@ $chatterFactories = [ 'bluesky' => Bridge\Bluesky\BlueskyTransportFactory::class, - 'brevo' => Bridge\Brevo\BrevoTransportFactory::class, 'chatwork' => Bridge\Chatwork\ChatworkTransportFactory::class, 'discord' => Bridge\Discord\DiscordTransportFactory::class, 'fake-chat' => Bridge\FakeChat\FakeChatTransportFactory::class, @@ -59,6 +58,7 @@ $texterFactories = [ 'all-my-sms' => Bridge\AllMySms\AllMySmsTransportFactory::class, 'bandwidth' => Bridge\Bandwidth\BandwidthTransportFactory::class, + 'brevo' => Bridge\Brevo\BrevoTransportFactory::class, 'click-send' => Bridge\ClickSend\ClickSendTransportFactory::class, 'clickatell' => Bridge\Clickatell\ClickatellTransportFactory::class, 'contact-everyone' => Bridge\ContactEveryone\ContactEveryoneTransportFactory::class, From a2c2e3c06f37bc7db3f08e9d91d5b9d5fb0c5022 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 17 Jun 2024 23:57:43 +0200 Subject: [PATCH 084/180] inject the missing logger service --- DependencyInjection/FrameworkExtension.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 437d5402a..3c82b4b0c 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2855,6 +2855,11 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ ->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } + if (ContainerBuilder::willBeAvailable('symfony/bluesky-notifier', NotifierBridge\Bluesky\BlueskyTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier'])) { + $container->getDefinition($classToServices[NotifierBridge\Bluesky\BlueskyTransportFactory::class]) + ->addArgument(new Reference('logger')); + } + if (isset($config['admin_recipients'])) { $notifier = $container->getDefinition('notifier'); foreach ($config['admin_recipients'] as $i => $recipient) { From 3b777e2fcb3ed5946ebb408413edbf8c593d3e2d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 17 Jun 2024 23:56:05 +0200 Subject: [PATCH 085/180] wire a clock for the BlueSky transport in the FrameworkBundle --- DependencyInjection/FrameworkExtension.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index b5d7930ac..942358181 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2865,6 +2865,12 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ ->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } + if (ContainerBuilder::willBeAvailable('symfony/bluesky-notifier', NotifierBridge\Bluesky\BlueskyTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier'])) { + $container->getDefinition($classToServices[NotifierBridge\Bluesky\BlueskyTransportFactory::class]) + ->addArgument(new Reference('logger')) + ->addArgument(new Reference('clock', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); + } + if (isset($config['admin_recipients'])) { $notifier = $container->getDefinition('notifier'); foreach ($config['admin_recipients'] as $i => $recipient) { From da2a0363c4d46f980e6abc0c48301820d38a8c36 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Sat, 15 Jun 2024 00:52:50 -0400 Subject: [PATCH 086/180] Simpler kernel setup with MicroKernelTrait --- CHANGELOG.md | 2 ++ Kernel/MicroKernelTrait.php | 17 +++++++++++++---- Tests/Kernel/ConcreteMicroKernel.php | 8 -------- Tests/Kernel/MicroKernelTraitTest.php | 17 +++++++++++------ Tests/Kernel/SimpleKernel.php | 25 +++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 Tests/Kernel/SimpleKernel.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 370786e61..f2470d542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * Add support for setting `headers` with `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` * Derivate `kernel.secret` from the decryption secret when its env var is not defined + * Make the `config/` directory optional in `MicroKernelTrait`, add support for service arguments in the + invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing 7.1 --- diff --git a/Kernel/MicroKernelTrait.php b/Kernel/MicroKernelTrait.php index b3f49c059..9e8237527 100644 --- a/Kernel/MicroKernelTrait.php +++ b/Kernel/MicroKernelTrait.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Kernel; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\AbstractConfigurator; @@ -48,7 +49,7 @@ trait MicroKernelTrait */ private function configureContainer(ContainerConfigurator $container, LoaderInterface $loader, ContainerBuilder $builder): void { - $configDir = $this->getConfigDir(); + $configDir = preg_replace('{/config$}', '/{config}', $this->getConfigDir()); $container->import($configDir.'/{packages}/*.{php,yaml}'); $container->import($configDir.'/{packages}/'.$this->environment.'/*.{php,yaml}'); @@ -73,7 +74,7 @@ private function configureContainer(ContainerConfigurator $container, LoaderInte */ private function configureRoutes(RoutingConfigurator $routes): void { - $configDir = $this->getConfigDir(); + $configDir = preg_replace('{/config$}', '/{config}', $this->getConfigDir()); $routes->import($configDir.'/{routes}/'.$this->environment.'/*.{php,yaml}'); $routes->import($configDir.'/{routes}/*.{php,yaml}'); @@ -84,7 +85,7 @@ private function configureRoutes(RoutingConfigurator $routes): void $routes->import($configDir.'/{routes}.php'); } - if (false !== ($fileName = (new \ReflectionObject($this))->getFileName())) { + if ($fileName = (new \ReflectionObject($this))->getFileName()) { $routes->import($fileName, 'attribute'); } } @@ -130,7 +131,13 @@ public function getLogDir(): string public function registerBundles(): iterable { - $contents = require $this->getBundlesPath(); + if (!is_file($bundlesPath = $this->getBundlesPath())) { + yield new FrameworkBundle(); + + return; + } + + $contents = require $bundlesPath; foreach ($contents as $class => $envs) { if ($envs[$this->environment] ?? $envs['all'] ?? false) { yield new $class(); @@ -216,6 +223,8 @@ public function loadRoutes(LoaderInterface $loader): RouteCollection $route->setDefault('_controller', ['kernel', $controller[1]]); } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !$r->isAnonymous()) { $route->setDefault('_controller', ['kernel', $r->name]); + } elseif ($this::class === $controller && method_exists($this, '__invoke')) { + $route->setDefault('_controller', 'kernel'); } } diff --git a/Tests/Kernel/ConcreteMicroKernel.php b/Tests/Kernel/ConcreteMicroKernel.php index fc5149699..a69618099 100644 --- a/Tests/Kernel/ConcreteMicroKernel.php +++ b/Tests/Kernel/ConcreteMicroKernel.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel; use Psr\Log\NullLogger; -use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -46,13 +45,6 @@ public function dangerousAction() throw new Danger(); } - public function registerBundles(): iterable - { - return [ - new FrameworkBundle(), - ]; - } - public function getCacheDir(): string { return $this->cacheDir = sys_get_temp_dir().'/sf_micro_kernel'; diff --git a/Tests/Kernel/MicroKernelTraitTest.php b/Tests/Kernel/MicroKernelTraitTest.php index 792acf5ef..eaa11eebe 100644 --- a/Tests/Kernel/MicroKernelTraitTest.php +++ b/Tests/Kernel/MicroKernelTraitTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; -use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; @@ -140,6 +139,17 @@ protected function configureRoutes(RoutingConfigurator $routes): void $this->assertSame('Hello World!', $response->getContent()); } + + public function testSimpleKernel() + { + $kernel = $this->kernel = new SimpleKernel('simple_kernel'); + $kernel->boot(); + + $request = Request::create('/'); + $response = $kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, false); + + $this->assertSame('Hello World!', $response->getContent()); + } } abstract class MinimalKernel extends Kernel @@ -155,11 +165,6 @@ public function __construct(string $cacheDir) $this->cacheDir = sys_get_temp_dir().'/'.$cacheDir; } - public function registerBundles(): iterable - { - yield new FrameworkBundle(); - } - public function getCacheDir(): string { return $this->cacheDir; diff --git a/Tests/Kernel/SimpleKernel.php b/Tests/Kernel/SimpleKernel.php new file mode 100644 index 000000000..f586e2dc5 --- /dev/null +++ b/Tests/Kernel/SimpleKernel.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel; + +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + +final class SimpleKernel extends MinimalKernel +{ + #[Route('/')] + public function __invoke(UrlGeneratorInterface $urlGenerator): Response + { + return new Response('Hello World!'); + } +} From cabdf4bfc1a2df7f3ec57893621a0af04139ffb8 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 19 Jun 2024 15:52:13 -0400 Subject: [PATCH 087/180] Fix kernel configuration loading --- Kernel/MicroKernelTrait.php | 4 +- Tests/Kernel/MicroKernelTraitTest.php | 14 +++++++ Tests/Kernel/default/config/bundles.php | 16 ++++++++ Tests/Kernel/default/config/routes.yaml | 3 ++ Tests/Kernel/default/config/services.yaml | 4 ++ Tests/Kernel/default/src/DefaultKernel.php | 43 ++++++++++++++++++++++ 6 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 Tests/Kernel/default/config/bundles.php create mode 100644 Tests/Kernel/default/config/routes.yaml create mode 100644 Tests/Kernel/default/config/services.yaml create mode 100644 Tests/Kernel/default/src/DefaultKernel.php diff --git a/Kernel/MicroKernelTrait.php b/Kernel/MicroKernelTrait.php index 9e8237527..f40373a30 100644 --- a/Kernel/MicroKernelTrait.php +++ b/Kernel/MicroKernelTrait.php @@ -54,7 +54,7 @@ private function configureContainer(ContainerConfigurator $container, LoaderInte $container->import($configDir.'/{packages}/*.{php,yaml}'); $container->import($configDir.'/{packages}/'.$this->environment.'/*.{php,yaml}'); - if (is_file($configDir.'/services.yaml')) { + if (is_file($this->getConfigDir().'/services.yaml')) { $container->import($configDir.'/services.yaml'); $container->import($configDir.'/{services}_'.$this->environment.'.yaml'); } else { @@ -79,7 +79,7 @@ private function configureRoutes(RoutingConfigurator $routes): void $routes->import($configDir.'/{routes}/'.$this->environment.'/*.{php,yaml}'); $routes->import($configDir.'/{routes}/*.{php,yaml}'); - if (is_file($configDir.'/routes.yaml')) { + if (is_file($this->getConfigDir().'/routes.yaml')) { $routes->import($configDir.'/routes.yaml'); } else { $routes->import($configDir.'/{routes}.php'); diff --git a/Tests/Kernel/MicroKernelTraitTest.php b/Tests/Kernel/MicroKernelTraitTest.php index eaa11eebe..a9d2ae720 100644 --- a/Tests/Kernel/MicroKernelTraitTest.php +++ b/Tests/Kernel/MicroKernelTraitTest.php @@ -25,6 +25,7 @@ use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; +require_once __DIR__.'/default/src/DefaultKernel.php'; require_once __DIR__.'/flex-style/src/FlexStyleMicroKernel.php'; class MicroKernelTraitTest extends TestCase @@ -150,6 +151,19 @@ public function testSimpleKernel() $this->assertSame('Hello World!', $response->getContent()); } + + public function testDefaultKernel() + { + $kernel = $this->kernel = new DefaultKernel('test', false); + $kernel->boot(); + + $this->assertTrue($kernel->getContainer()->has('foo_service')); + + $request = Request::create('/'); + $response = $kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, false); + + $this->assertSame('OK', $response->getContent()); + } } abstract class MinimalKernel extends Kernel diff --git a/Tests/Kernel/default/config/bundles.php b/Tests/Kernel/default/config/bundles.php new file mode 100644 index 000000000..fbde1ef1c --- /dev/null +++ b/Tests/Kernel/default/config/bundles.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; + +return [ + FrameworkBundle::class => ['all' => true], +]; diff --git a/Tests/Kernel/default/config/routes.yaml b/Tests/Kernel/default/config/routes.yaml new file mode 100644 index 000000000..5653fe0b9 --- /dev/null +++ b/Tests/Kernel/default/config/routes.yaml @@ -0,0 +1,3 @@ +welcome: + path: / + controller: 'kernel' diff --git a/Tests/Kernel/default/config/services.yaml b/Tests/Kernel/default/config/services.yaml new file mode 100644 index 000000000..fa0d7df8e --- /dev/null +++ b/Tests/Kernel/default/config/services.yaml @@ -0,0 +1,4 @@ +services: + foo_service: + class: stdClass + public: true diff --git a/Tests/Kernel/default/src/DefaultKernel.php b/Tests/Kernel/default/src/DefaultKernel.php new file mode 100644 index 000000000..93d120793 --- /dev/null +++ b/Tests/Kernel/default/src/DefaultKernel.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel; + +use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Kernel; + +class DefaultKernel extends Kernel +{ + use MicroKernelTrait; + + public function __invoke(): Response + { + return new Response('OK'); + } + + private string $cacheDir; + + public function getCacheDir(): string + { + return $this->cacheDir ??= sys_get_temp_dir().'/sf_default_kernel'; + } + + public function getLogDir(): string + { + return $this->cacheDir; + } + + public function getProjectDir(): string + { + return \dirname(__DIR__); + } +} From af5de4e04cd54dd7e3ac42a32c18f8ad545a0832 Mon Sep 17 00:00:00 2001 From: Patrick Landolt Date: Sun, 9 Jun 2024 17:30:25 +0200 Subject: [PATCH 088/180] [Mailer] Add mailomat bridge --- DependencyInjection/FrameworkExtension.php | 2 ++ Resources/config/mailer_transports.php | 2 ++ Resources/config/mailer_webhook.php | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 942358181..7119002cb 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2620,6 +2620,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co 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\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', @@ -2643,6 +2644,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\MailerSend\Webhook\MailerSendRequestParser::class => 'mailer.webhook.request_parser.mailersend', 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\Resend\Webhook\ResendRequestParser::class => 'mailer.webhook.request_parser.resend', MailerBridge\Sendgrid\Webhook\SendgridRequestParser::class => 'mailer.webhook.request_parser.sendgrid', diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index 5434b4c56..bdcd7e9c6 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -20,6 +20,7 @@ use Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; +use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; @@ -52,6 +53,7 @@ 'mailersend' => MailerSendTransportFactory::class, 'mailgun' => MailgunTransportFactory::class, 'mailjet' => MailjetTransportFactory::class, + 'mailomat' => MailomatTransportFactory::class, 'mailpace' => MailPaceTransportFactory::class, 'native' => NativeTransportFactory::class, 'null' => NullTransportFactory::class, diff --git a/Resources/config/mailer_webhook.php b/Resources/config/mailer_webhook.php index f9d2b9686..64020c1b1 100644 --- a/Resources/config/mailer_webhook.php +++ b/Resources/config/mailer_webhook.php @@ -19,6 +19,8 @@ use Symfony\Component\Mailer\Bridge\Mailgun\Webhook\MailgunRequestParser; use Symfony\Component\Mailer\Bridge\Mailjet\RemoteEvent\MailjetPayloadConverter; use Symfony\Component\Mailer\Bridge\Mailjet\Webhook\MailjetRequestParser; +use Symfony\Component\Mailer\Bridge\Mailomat\RemoteEvent\MailomatPayloadConverter; +use Symfony\Component\Mailer\Bridge\Mailomat\Webhook\MailomatRequestParser; use Symfony\Component\Mailer\Bridge\Postmark\RemoteEvent\PostmarkPayloadConverter; use Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser; use Symfony\Component\Mailer\Bridge\Resend\RemoteEvent\ResendPayloadConverter; @@ -48,6 +50,11 @@ ->args([service('mailer.payload_converter.mailjet')]) ->alias(MailjetRequestParser::class, 'mailer.webhook.request_parser.mailjet') + ->set('mailer.payload_converter.mailomat', MailomatPayloadConverter::class) + ->set('mailer.webhook.request_parser.mailomat', MailomatRequestParser::class) + ->args([service('mailer.payload_converter.mailomat')]) + ->alias(MailomatRequestParser::class, 'mailer.webhook.request_parser.mailomat') + ->set('mailer.payload_converter.postmark', PostmarkPayloadConverter::class) ->set('mailer.webhook.request_parser.postmark', PostmarkRequestParser::class) ->args([service('mailer.payload_converter.postmark')]) From 4875a8487ff2d8d577500fc135b8fa570f845a0a Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 20 Jun 2024 17:52:34 +0200 Subject: [PATCH 089/180] Prefix all sprintf() calls --- CacheWarmer/RouterCacheWarmer.php | 2 +- Command/AbstractConfigCommand.php | 12 +-- Command/AssetsInstallCommand.php | 12 +-- Command/CacheClearCommand.php | 8 +- Command/CachePoolClearCommand.php | 10 +-- Command/CachePoolDeleteCommand.php | 6 +- Command/CachePoolInvalidateTagsCommand.php | 8 +- Command/CachePoolPruneCommand.php | 2 +- Command/CacheWarmupCommand.php | 4 +- Command/ConfigDebugCommand.php | 14 ++-- Command/ConfigDumpReferenceCommand.php | 16 ++-- Command/ContainerDebugCommand.php | 12 +-- Command/ContainerLintCommand.php | 4 +- Command/DebugAutowiringCommand.php | 10 +-- Command/EventDispatcherDebugCommand.php | 6 +- Command/RouterDebugCommand.php | 4 +- Command/RouterMatchCommand.php | 8 +- Command/SecretsDecryptToLocalCommand.php | 6 +- Command/SecretsListCommand.php | 2 +- Command/SecretsRevealCommand.php | 2 +- Command/SecretsSetCommand.php | 6 +- Command/TranslationDebugCommand.php | 12 +-- Command/TranslationUpdateCommand.php | 14 ++-- Command/WorkflowDumpCommand.php | 2 +- Console/Application.php | 2 +- Console/Descriptor/Descriptor.php | 4 +- Console/Descriptor/JsonDescriptor.php | 8 +- Console/Descriptor/MarkdownDescriptor.php | 64 +++++++-------- Console/Descriptor/TextDescriptor.php | 70 ++++++++--------- Console/Descriptor/XmlDescriptor.php | 8 +- Controller/AbstractController.php | 6 +- Controller/ControllerResolver.php | 2 +- Controller/RedirectController.php | 4 +- DependencyInjection/Compiler/ProfilerPass.php | 2 +- .../Compiler/UnusedTagsPass.php | 4 +- DependencyInjection/Configuration.php | 6 +- DependencyInjection/FrameworkExtension.php | 78 +++++++++---------- EventListener/ConsoleProfilerListener.php | 2 +- .../SuggestMissingPackageSubscriber.php | 2 +- KernelBrowser.php | 4 +- Resources/config/cache.php | 4 +- Resources/config/collectors.php | 2 +- Resources/config/services.php | 2 +- Routing/Router.php | 6 +- Secrets/AbstractVault.php | 2 +- Secrets/DotenvVault.php | 8 +- Secrets/SodiumVault.php | 28 +++---- Test/BrowserKitAssertionsTrait.php | 2 +- Test/DomCrawlerAssertionsTrait.php | 8 +- Test/HttpClientAssertionsTrait.php | 6 +- Test/KernelTestCase.php | 4 +- Test/TestContainer.php | 2 +- Test/WebTestCase.php | 2 +- .../CacheClearCommandTest.php | 4 +- .../Descriptor/AbstractDescriptorTestCase.php | 8 +- .../Console/Descriptor/TextDescriptorTest.php | 2 +- Tests/Controller/TestAbstractController.php | 4 +- .../Compiler/UnusedTagsPassTest.php | 2 +- .../FrameworkExtensionTestCase.php | 22 +++--- .../Controller/SessionController.php | 4 +- .../Functional/CacheAttributeListenerTest.php | 4 +- Tests/Functional/ConfigDebugCommandTest.php | 2 +- .../Functional/ContainerDebugCommandTest.php | 6 +- Tests/Functional/app/AppKernel.php | 6 +- Translation/Translator.php | 2 +- 65 files changed, 295 insertions(+), 295 deletions(-) diff --git a/CacheWarmer/RouterCacheWarmer.php b/CacheWarmer/RouterCacheWarmer.php index eed548046..149d20ce3 100644 --- a/CacheWarmer/RouterCacheWarmer.php +++ b/CacheWarmer/RouterCacheWarmer.php @@ -46,7 +46,7 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array return (array) $router->warmUp($cacheDir, $buildDir); } - throw new \LogicException(sprintf('The router "%s" cannot be warmed up because it does not implement "%s".', get_debug_type($router), WarmableInterface::class)); + throw new \LogicException(\sprintf('The router "%s" cannot be warmed up because it does not implement "%s".', get_debug_type($router), WarmableInterface::class)); } public function isOptional(): bool diff --git a/Command/AbstractConfigCommand.php b/Command/AbstractConfigCommand.php index 479bbfe6a..fc3433c2d 100644 --- a/Command/AbstractConfigCommand.php +++ b/Command/AbstractConfigCommand.php @@ -114,7 +114,7 @@ protected function findExtension(string $name): ExtensionInterface foreach ($bundles as $bundle) { if ($name === $bundle->getName()) { if (!$bundle->getContainerExtension()) { - throw new \LogicException(sprintf('Bundle "%s" does not have a container extension.', $name)); + throw new \LogicException(\sprintf('Bundle "%s" does not have a container extension.', $name)); } return $bundle->getContainerExtension(); @@ -144,13 +144,13 @@ protected function findExtension(string $name): ExtensionInterface } if (!str_ends_with($name, 'Bundle')) { - $message = sprintf('No extensions with configuration available for "%s".', $name); + $message = \sprintf('No extensions with configuration available for "%s".', $name); } else { - $message = sprintf('No extension with alias "%s" is enabled.', $name); + $message = \sprintf('No extension with alias "%s" is enabled.', $name); } if (isset($guess) && $minScore < 3) { - $message .= sprintf("\n\nDid you mean \"%s\"?", $guess); + $message .= \sprintf("\n\nDid you mean \"%s\"?", $guess); } throw new LogicException($message); @@ -159,11 +159,11 @@ protected function findExtension(string $name): ExtensionInterface public function validateConfiguration(ExtensionInterface $extension, mixed $configuration): void { if (!$configuration) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have its getConfiguration() method setup.', $extension->getAlias())); + throw new \LogicException(\sprintf('The extension with alias "%s" does not have its getConfiguration() method setup.', $extension->getAlias())); } if (!$configuration instanceof ConfigurationInterface) { - throw new \LogicException(sprintf('Configuration class "%s" should implement ConfigurationInterface in order to be dumpable.', get_debug_type($configuration))); + throw new \LogicException(\sprintf('Configuration class "%s" should implement ConfigurationInterface in order to be dumpable.', get_debug_type($configuration))); } } diff --git a/Command/AssetsInstallCommand.php b/Command/AssetsInstallCommand.php index 32b38de9a..5dc8c828e 100644 --- a/Command/AssetsInstallCommand.php +++ b/Command/AssetsInstallCommand.php @@ -93,7 +93,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $targetArg = $kernel->getProjectDir().'/'.$targetArg; if (!is_dir($targetArg)) { - throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $targetArg)); + throw new InvalidArgumentException(\sprintf('The target directory "%s" does not exist.', $targetArg)); } } @@ -130,7 +130,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $validAssetDirs[] = $assetDir; if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir); + $message = \sprintf("%s\n-> %s", $bundle->getName(), $targetDir); } else { $message = $bundle->getName(); } @@ -151,13 +151,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($method === $expectedMethod) { - $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method]; + $rows[] = [\sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method]; } else { - $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method]; + $rows[] = [\sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method]; } } catch (\Exception $e) { $exitCode = 1; - $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage()]; + $rows[] = [\sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage()]; } } // remove the assets of the bundles that no longer exist @@ -230,7 +230,7 @@ private function symlink(string $originDir, string $targetDir, bool $relative = } $this->filesystem->symlink($originDir, $targetDir); if (!file_exists($targetDir)) { - throw new IOException(sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir); + throw new IOException(\sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir); } } diff --git a/Command/CacheClearCommand.php b/Command/CacheClearCommand.php index 55813664b..4ef2f5a1d 100644 --- a/Command/CacheClearCommand.php +++ b/Command/CacheClearCommand.php @@ -80,7 +80,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $fs->remove($oldCacheDir); if (!is_writable($realCacheDir)) { - throw new RuntimeException(sprintf('Unable to write in the "%s" directory.', $realCacheDir)); + throw new RuntimeException(\sprintf('Unable to write in the "%s" directory.', $realCacheDir)); } $useBuildDir = $realBuildDir !== $realCacheDir; @@ -89,7 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $fs->remove($oldBuildDir); if (!is_writable($realBuildDir)) { - throw new RuntimeException(sprintf('Unable to write in the "%s" directory.', $realBuildDir)); + throw new RuntimeException(\sprintf('Unable to write in the "%s" directory.', $realBuildDir)); } if ($this->isNfs($realCacheDir)) { @@ -100,7 +100,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $fs->mkdir($realCacheDir); } - $io->comment(sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + $io->comment(\sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); if ($useBuildDir) { $this->cacheClearer->clear($realBuildDir); } @@ -189,7 +189,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->comment('Finished'); } - $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + $io->success(\sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); return 0; } diff --git a/Command/CachePoolClearCommand.php b/Command/CachePoolClearCommand.php index d5320e7a9..5d840e597 100644 --- a/Command/CachePoolClearCommand.php +++ b/Command/CachePoolClearCommand.php @@ -95,28 +95,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int } elseif ($pool instanceof Psr6CacheClearer) { $clearers[$id] = $pool; } else { - throw new InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id)); + throw new InvalidArgumentException(\sprintf('"%s" is not a cache pool nor a cache clearer.', $id)); } } } foreach ($clearers as $id => $clearer) { - $io->comment(sprintf('Calling cache clearer: %s', $id)); + $io->comment(\sprintf('Calling cache clearer: %s', $id)); $clearer->clear($kernel->getContainer()->getParameter('kernel.cache_dir')); } $failure = false; foreach ($pools as $id => $pool) { - $io->comment(sprintf('Clearing cache pool: %s', $id)); + $io->comment(\sprintf('Clearing cache pool: %s', $id)); if ($pool instanceof CacheItemPoolInterface) { if (!$pool->clear()) { - $io->warning(sprintf('Cache pool "%s" could not be cleared.', $pool)); + $io->warning(\sprintf('Cache pool "%s" could not be cleared.', $pool)); $failure = true; } } else { if (false === $this->poolClearer->clearPool($id)) { - $io->warning(sprintf('Cache pool "%s" could not be cleared.', $pool)); + $io->warning(\sprintf('Cache pool "%s" could not be cleared.', $pool)); $failure = true; } } diff --git a/Command/CachePoolDeleteCommand.php b/Command/CachePoolDeleteCommand.php index e634e00f0..8fb1d1aaa 100644 --- a/Command/CachePoolDeleteCommand.php +++ b/Command/CachePoolDeleteCommand.php @@ -63,16 +63,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int $cachePool = $this->poolClearer->getPool($pool); if (!$cachePool->hasItem($key)) { - $io->note(sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); + $io->note(\sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); return 0; } if (!$cachePool->deleteItem($key)) { - throw new \Exception(sprintf('Cache item "%s" could not be deleted.', $key)); + throw new \Exception(\sprintf('Cache item "%s" could not be deleted.', $key)); } - $io->success(sprintf('Cache item "%s" was successfully deleted.', $key)); + $io->success(\sprintf('Cache item "%s" was successfully deleted.', $key)); return 0; } diff --git a/Command/CachePoolInvalidateTagsCommand.php b/Command/CachePoolInvalidateTagsCommand.php index f879a6d0d..f92f0d634 100644 --- a/Command/CachePoolInvalidateTagsCommand.php +++ b/Command/CachePoolInvalidateTagsCommand.php @@ -64,26 +64,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int $errors = false; foreach ($pools as $name) { - $io->comment(sprintf('Invalidating tag(s): %s from pool %s.', $tagList, $name)); + $io->comment(\sprintf('Invalidating tag(s): %s from pool %s.', $tagList, $name)); try { $pool = $this->pools->get($name); } catch (ServiceNotFoundException) { - $io->error(sprintf('Pool "%s" not found.', $name)); + $io->error(\sprintf('Pool "%s" not found.', $name)); $errors = true; continue; } if (!$pool instanceof TagAwareCacheInterface) { - $io->error(sprintf('Pool "%s" is not taggable.', $name)); + $io->error(\sprintf('Pool "%s" is not taggable.', $name)); $errors = true; continue; } if (!$pool->invalidateTags($tags)) { - $io->error(sprintf('Cache tag(s) "%s" could not be invalidated for pool "%s".', $tagList, $name)); + $io->error(\sprintf('Cache tag(s) "%s" could not be invalidated for pool "%s".', $tagList, $name)); $errors = true; } } diff --git a/Command/CachePoolPruneCommand.php b/Command/CachePoolPruneCommand.php index fba1033f9..745a001cc 100644 --- a/Command/CachePoolPruneCommand.php +++ b/Command/CachePoolPruneCommand.php @@ -52,7 +52,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io = new SymfonyStyle($input, $output); foreach ($this->pools as $name => $pool) { - $io->comment(sprintf('Pruning cache pool: %s', $name)); + $io->comment(\sprintf('Pruning cache pool: %s', $name)); $pool->prune(); } diff --git a/Command/CacheWarmupCommand.php b/Command/CacheWarmupCommand.php index a4b32a561..b096b0801 100644 --- a/Command/CacheWarmupCommand.php +++ b/Command/CacheWarmupCommand.php @@ -58,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io = new SymfonyStyle($input, $output); $kernel = $this->getApplication()->getKernel(); - $io->comment(sprintf('Warming up the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + $io->comment(\sprintf('Warming up the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); if (!$input->getOption('no-optional-warmers')) { $this->cacheWarmer->enableOptionalWarmers(); @@ -76,7 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int Preloader::append($preloadFile, $preload); } - $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + $io->success(\sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); return 0; } diff --git a/Command/ConfigDebugCommand.php b/Command/ConfigDebugCommand.php index cc116fc68..fb79b39bf 100644 --- a/Command/ConfigDebugCommand.php +++ b/Command/ConfigDebugCommand.php @@ -41,7 +41,7 @@ class ConfigDebugCommand extends AbstractConfigCommand { protected function configure(): void { - $commentedHelpFormats = array_map(fn ($format) => sprintf('%s', $format), $this->getAvailableFormatOptions()); + $commentedHelpFormats = array_map(fn ($format) => \sprintf('%s', $format), $this->getAvailableFormatOptions()); $helpFormats = implode('", "', $commentedHelpFormats); $this @@ -49,7 +49,7 @@ protected function configure(): void new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), new InputOption('resolve-env', null, InputOption::VALUE_NONE, 'Display resolved environment variable values instead of placeholders'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), class_exists(Yaml::class) ? 'txt' : 'json'), + 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 @@ -106,7 +106,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (null === $path = $input->getArgument('path')) { if ('txt' === $input->getOption('format')) { $io->title( - sprintf('Current configuration for %s', $name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name)) + \sprintf('Current configuration for %s', $name === $extensionAlias ? \sprintf('extension with alias "%s"', $extensionAlias) : \sprintf('"%s"', $name)) ); } @@ -123,7 +123,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path)); + $io->title(\sprintf('Current configuration for "%s.%s"', $extensionAlias, $path)); $io->writeln($this->convertToFormat($config, $format)); @@ -135,7 +135,7 @@ private function convertToFormat(mixed $config, string $format): string return match ($format) { 'txt', 'yaml' => Yaml::dump($config, 10), 'json' => json_encode($config, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE), - default => throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))), + default => throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))), }; } @@ -162,7 +162,7 @@ private function getConfigForPath(array $config, string $path, string $alias): m foreach ($steps as $step) { if (!\array_key_exists($step, $config)) { - throw new LogicException(sprintf('Unable to find configuration for "%s.%s".', $alias, $path)); + throw new LogicException(\sprintf('Unable to find configuration for "%s.%s".', $alias, $path)); } $config = $config[$step]; @@ -190,7 +190,7 @@ private function getConfigForExtension(ExtensionInterface $extension, ContainerB // Fall back to default config if the extension has one if (!$extension instanceof ConfigurationExtensionInterface && !$extension instanceof ConfigurationInterface) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); + throw new \LogicException(\sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); } $configs = $container->getExtensionConfig($extensionAlias); diff --git a/Command/ConfigDumpReferenceCommand.php b/Command/ConfigDumpReferenceCommand.php index 3231e5a47..27dc01b11 100644 --- a/Command/ConfigDumpReferenceCommand.php +++ b/Command/ConfigDumpReferenceCommand.php @@ -39,14 +39,14 @@ class ConfigDumpReferenceCommand extends AbstractConfigCommand { protected function configure(): void { - $commentedHelpFormats = array_map(fn ($format) => sprintf('%s', $format), $this->getAvailableFormatOptions()); + $commentedHelpFormats = array_map(fn ($format) => \sprintf('%s', $format), $this->getAvailableFormatOptions()); $helpFormats = implode('", "', $commentedHelpFormats); $this ->setDefinition([ new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'yaml'), + 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 @@ -118,27 +118,27 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($name === $extension->getAlias()) { - $message = sprintf('Default configuration for extension with alias: "%s"', $name); + $message = \sprintf('Default configuration for extension with alias: "%s"', $name); } else { - $message = sprintf('Default configuration for "%s"', $name); + $message = \sprintf('Default configuration for "%s"', $name); } if (null !== $path) { - $message .= sprintf(' at path "%s"', $path); + $message .= \sprintf(' at path "%s"', $path); } switch ($format) { case 'yaml': - $io->writeln(sprintf('# %s', $message)); + $io->writeln(\sprintf('# %s', $message)); $dumper = new YamlReferenceDumper(); break; case 'xml': - $io->writeln(sprintf('', $message)); + $io->writeln(\sprintf('', $message)); $dumper = new XmlReferenceDumper(); break; default: $io->writeln($message); - throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))); + throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))); } $io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path)); diff --git a/Command/ContainerDebugCommand.php b/Command/ContainerDebugCommand.php index df6aef5dd..9619d1972 100644 --- a/Command/ContainerDebugCommand.php +++ b/Command/ContainerDebugCommand.php @@ -52,7 +52,7 @@ protected function configure(): void new InputOption('types', null, InputOption::VALUE_NONE, 'Display types (classes/interfaces) available in the container'), new InputOption('env-var', null, InputOption::VALUE_REQUIRED, 'Display a specific environment variable used in the container'), new InputOption('env-vars', null, InputOption::VALUE_NONE, 'Display environment variables used in the container'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), new InputOption('deprecations', null, InputOption::VALUE_NONE, 'Display deprecations generated when compiling and warming up the container'), ]) @@ -171,19 +171,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($object->hasDefinition($options['id'])) { $definition = $object->getDefinition($options['id']); if ($definition->isDeprecated()) { - $errorIo->warning($definition->getDeprecation($options['id'])['message'] ?? sprintf('The "%s" service is deprecated.', $options['id'])); + $errorIo->warning($definition->getDeprecation($options['id'])['message'] ?? \sprintf('The "%s" service is deprecated.', $options['id'])); } } if ($object->hasAlias($options['id'])) { $alias = $object->getAlias($options['id']); if ($alias->isDeprecated()) { - $errorIo->warning($alias->getDeprecation($options['id'])['message'] ?? sprintf('The "%s" alias is deprecated.', $options['id'])); + $errorIo->warning($alias->getDeprecation($options['id'])['message'] ?? \sprintf('The "%s" alias is deprecated.', $options['id'])); } } } if (isset($options['id']) && isset($kernel->getContainer()->getRemovedIds()[$options['id']])) { - $errorIo->note(sprintf('The "%s" service or alias has been removed or inlined when the container was compiled.', $options['id'])); + $errorIo->note(\sprintf('The "%s" service or alias has been removed or inlined when the container was compiled.', $options['id'])); } } catch (ServiceNotFoundException $e) { if ('' !== $e->getId() && '@' === $e->getId()[0]) { @@ -277,7 +277,7 @@ private function findProperServiceName(InputInterface $input, SymfonyStyle $io, $matchingServices = $this->findServiceIdsContaining($container, $name, $showHidden); if (!$matchingServices) { - throw new InvalidArgumentException(sprintf('No services found that match "%s".', $name)); + throw new InvalidArgumentException(\sprintf('No services found that match "%s".', $name)); } if (1 === \count($matchingServices)) { @@ -295,7 +295,7 @@ private function findProperTagName(InputInterface $input, SymfonyStyle $io, Cont $matchingTags = $this->findTagsContaining($container, $tagName); if (!$matchingTags) { - throw new InvalidArgumentException(sprintf('No tags found that match "%s".', $tagName)); + throw new InvalidArgumentException(\sprintf('No tags found that match "%s".', $tagName)); } if (1 === \count($matchingTags)) { diff --git a/Command/ContainerLintCommand.php b/Command/ContainerLintCommand.php index cd6e0657c..0e6c72d16 100644 --- a/Command/ContainerLintCommand.php +++ b/Command/ContainerLintCommand.php @@ -81,7 +81,7 @@ private function getContainerBuilder(): ContainerBuilder if (!$kernel->isDebug() || !$kernelContainer->getParameter('debug.container.dump') || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) { if (!$kernel instanceof Kernel) { - throw new RuntimeException(sprintf('This command does not support the application kernel: "%s" does not extend "%s".', get_debug_type($kernel), Kernel::class)); + throw new RuntimeException(\sprintf('This command does not support the application kernel: "%s" does not extend "%s".', get_debug_type($kernel), Kernel::class)); } $buildContainer = \Closure::bind(function (): ContainerBuilder { @@ -92,7 +92,7 @@ private function getContainerBuilder(): ContainerBuilder $container = $buildContainer(); } else { if (!$kernelContainer instanceof Container) { - throw new RuntimeException(sprintf('This command does not support the application container: "%s" does not extend "%s".', get_debug_type($kernelContainer), Container::class)); + throw new RuntimeException(\sprintf('This command does not support the application container: "%s" does not extend "%s".', get_debug_type($kernelContainer), Container::class)); } (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); diff --git a/Command/DebugAutowiringCommand.php b/Command/DebugAutowiringCommand.php index 77011b185..e159c5a39 100644 --- a/Command/DebugAutowiringCommand.php +++ b/Command/DebugAutowiringCommand.php @@ -77,7 +77,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $serviceIds = array_filter($serviceIds, 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)); + $errorIo->error(\sprintf('No autowirable classes or interfaces found matching "%s"', $search)); return 1; } @@ -96,7 +96,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->title('Autowirable Types'); $io->text('The following classes & interfaces can be used as type-hints when autowiring:'); if ($search) { - $io->text(sprintf('(only showing classes/interfaces matching %s)', $search)); + $io->text(\sprintf('(only showing classes/interfaces matching %s)', $search)); } $hasAlias = []; $all = $input->getOption('all'); @@ -119,10 +119,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } - $serviceLine = sprintf('%s', $serviceId); + $serviceLine = \sprintf('%s', $serviceId); if ('' !== $fileLink = $this->getFileLink($previousId)) { $serviceLine = substr($serviceId, \strlen($previousId)); - $serviceLine = sprintf('%s', $fileLink, $previousId).('' !== $serviceLine ? sprintf('%s', $serviceLine) : ''); + $serviceLine = \sprintf('%s', $fileLink, $previousId).('' !== $serviceLine ? \sprintf('%s', $serviceLine) : ''); } if ($container->hasAlias($serviceId)) { @@ -167,7 +167,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->newLine(); if (0 < $serviceIdsNb) { - $io->text(sprintf('%s more concrete service%s would be displayed when adding the "--all" option.', $serviceIdsNb, $serviceIdsNb > 1 ? 's' : '')); + $io->text(\sprintf('%s more concrete service%s would be displayed when adding the "--all" option.', $serviceIdsNb, $serviceIdsNb > 1 ? 's' : '')); } if ($all) { $io->text('Pro-tip: use interfaces in your type-hints instead of classes to benefit from the dependency inversion principle.'); diff --git a/Command/EventDispatcherDebugCommand.php b/Command/EventDispatcherDebugCommand.php index 52816e7de..a3531d800 100644 --- a/Command/EventDispatcherDebugCommand.php +++ b/Command/EventDispatcherDebugCommand.php @@ -49,7 +49,7 @@ protected function configure(): void ->setDefinition([ new InputArgument('event', InputArgument::OPTIONAL, 'An event name or a part of the event name'), new InputOption('dispatcher', null, InputOption::VALUE_REQUIRED, 'To view events of a specific event dispatcher', self::DEFAULT_DISPATCHER), - new InputOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), ]) ->setHelp(<<<'EOF' @@ -75,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $options = []; $dispatcherServiceName = $input->getOption('dispatcher'); if (!$this->dispatchers->has($dispatcherServiceName)) { - $io->getErrorStyle()->error(sprintf('Event dispatcher "%s" is not available.', $dispatcherServiceName)); + $io->getErrorStyle()->error(\sprintf('Event dispatcher "%s" is not available.', $dispatcherServiceName)); return 1; } @@ -89,7 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int // if there is no direct match, try find partial matches $events = $this->searchForEvent($dispatcher, $event); if (0 === \count($events)) { - $io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event)); + $io->getErrorStyle()->warning(\sprintf('The event "%s" does not have any registered listeners.', $event)); return 0; } elseif (1 === \count($events)) { diff --git a/Command/RouterDebugCommand.php b/Command/RouterDebugCommand.php index 54df49431..d57c0623f 100644 --- a/Command/RouterDebugCommand.php +++ b/Command/RouterDebugCommand.php @@ -53,7 +53,7 @@ protected function configure(): void new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), new InputOption('show-aliases', null, InputOption::VALUE_NONE, 'Show aliases in overview'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)'), ]) ->setHelp(<<<'EOF' @@ -103,7 +103,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if (!$route) { - throw new InvalidArgumentException(sprintf('The route "%s" does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The route "%s" does not exist.', $name)); } $helper->describe($io, $route, [ diff --git a/Command/RouterMatchCommand.php b/Command/RouterMatchCommand.php index 475b403ca..3f0ea3cb5 100644 --- a/Command/RouterMatchCommand.php +++ b/Command/RouterMatchCommand.php @@ -93,21 +93,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int $matches = false; foreach ($traces as $trace) { if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) { - $io->text(sprintf('Route "%s" almost matches but %s', $trace['name'], lcfirst($trace['log']))); + $io->text(\sprintf('Route "%s" almost matches but %s', $trace['name'], lcfirst($trace['log']))); } elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) { - $io->success(sprintf('Route "%s" matches', $trace['name'])); + $io->success(\sprintf('Route "%s" matches', $trace['name'])); $routerDebugCommand = $this->getApplication()->find('debug:router'); $routerDebugCommand->run(new ArrayInput(['name' => $trace['name']]), $output); $matches = true; } elseif ($input->getOption('verbose')) { - $io->text(sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log'])); + $io->text(\sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log'])); } } if (!$matches) { - $io->error(sprintf('None of the routes match the path "%s"', $input->getArgument('path_info'))); + $io->error(\sprintf('None of the routes match the path "%s"', $input->getArgument('path_info'))); return 1; } diff --git a/Command/SecretsDecryptToLocalCommand.php b/Command/SecretsDecryptToLocalCommand.php index f76e1d05a..b078769d8 100644 --- a/Command/SecretsDecryptToLocalCommand.php +++ b/Command/SecretsDecryptToLocalCommand.php @@ -64,7 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $secrets = $this->vault->list(true); - $io->comment(sprintf('%d secret%s found in the vault.', \count($secrets), 1 !== \count($secrets) ? 's' : '')); + $io->comment(\sprintf('%d secret%s found in the vault.', \count($secrets), 1 !== \count($secrets) ? 's' : '')); $skipped = 0; if (!$input->getOption('force')) { @@ -78,14 +78,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($skipped > 0) { $io->warning([ - sprintf('%d secret%s already overridden in the local vault and will be skipped.', $skipped, 1 !== $skipped ? 's are' : ' is'), + \sprintf('%d secret%s already overridden in the local vault and will be skipped.', $skipped, 1 !== $skipped ? 's are' : ' is'), 'Use the --force flag to override these.', ]); } foreach ($secrets as $k => $v) { if (null === $v) { - $io->error($this->vault->getLastMessage() ?? sprintf('Secret "%s" has been skipped as there was an error reading it.', $k)); + $io->error($this->vault->getLastMessage() ?? \sprintf('Secret "%s" has been skipped as there was an error reading it.', $k)); continue; } diff --git a/Command/SecretsListCommand.php b/Command/SecretsListCommand.php index cdfc51c39..920b3b1fc 100644 --- a/Command/SecretsListCommand.php +++ b/Command/SecretsListCommand.php @@ -62,7 +62,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->comment('Use "%env()%" to reference a secret in a config file.'); if (!$reveal = $input->getOption('reveal')) { - $io->comment(sprintf('To reveal the secrets run php %s %s --reveal', $_SERVER['PHP_SELF'], $this->getName())); + $io->comment(\sprintf('To reveal the secrets run php %s %s --reveal', $_SERVER['PHP_SELF'], $this->getName())); } $secrets = $this->vault->list($reveal); diff --git a/Command/SecretsRevealCommand.php b/Command/SecretsRevealCommand.php index bcbdea11f..150186b1d 100644 --- a/Command/SecretsRevealCommand.php +++ b/Command/SecretsRevealCommand.php @@ -59,7 +59,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->writeln($localSecrets[$name]); } else { if (!\array_key_exists($name, $secrets)) { - $io->error(sprintf('The secret "%s" does not exist.', $name)); + $io->error(\sprintf('The secret "%s" does not exist.', $name)); return self::INVALID; } diff --git a/Command/SecretsSetCommand.php b/Command/SecretsSetCommand.php index 49a20af76..f7e8eeaa6 100644 --- a/Command/SecretsSetCommand.php +++ b/Command/SecretsSetCommand.php @@ -84,7 +84,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($this->localVault === $vault && !\array_key_exists($name, $this->vault->list())) { - $io->error(sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name)); + $io->error(\sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name)); return 1; } @@ -103,9 +103,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int } elseif (is_file($file) && is_readable($file)) { $value = file_get_contents($file); } elseif (!is_file($file)) { - throw new \InvalidArgumentException(sprintf('File not found: "%s".', $file)); + throw new \InvalidArgumentException(\sprintf('File not found: "%s".', $file)); } elseif (!is_readable($file)) { - throw new \InvalidArgumentException(sprintf('File is not readable: "%s".', $file)); + throw new \InvalidArgumentException(\sprintf('File is not readable: "%s".', $file)); } if ($vault->generateKeys()) { diff --git a/Command/TranslationDebugCommand.php b/Command/TranslationDebugCommand.php index 2438d3feb..9cdfdae04 100644 --- a/Command/TranslationDebugCommand.php +++ b/Command/TranslationDebugCommand.php @@ -145,7 +145,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $codePaths = [$path.'/templates']; if (!is_dir($transPaths[0])) { - throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); + throw new InvalidArgumentException(\sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); } } } elseif ($input->getOption('all')) { @@ -171,10 +171,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int // No defined or extracted messages if (!$allMessages || null !== $domain && empty($allMessages[$domain])) { - $outputMessage = sprintf('No defined or extracted messages for locale "%s"', $locale); + $outputMessage = \sprintf('No defined or extracted messages for locale "%s"', $locale); if (null !== $domain) { - $outputMessage .= sprintf(' and domain "%s"', $domain); + $outputMessage .= \sprintf(' and domain "%s"', $domain); } $io->getErrorStyle()->warning($outputMessage); @@ -186,9 +186,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths); // Display header line - $headers = ['State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale)]; + $headers = ['State', 'Domain', 'Id', \sprintf('Message Preview (%s)', $locale)]; foreach ($fallbackCatalogues as $fallbackCatalogue) { - $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale()); + $headers[] = \sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale()); } $rows = []; // Iterate all message ids and determine their state @@ -310,7 +310,7 @@ private function formatStates(array $states): string private function formatId(string $id): string { - return sprintf('%s', $id); + return \sprintf('%s', $id); } private function sanitizeString(string $string, int $length = 40): string diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index 1a883f81e..2f61c81d6 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -172,13 +172,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int $codePaths = [$path.'/templates']; if (!is_dir($transPaths[0])) { - throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); + throw new InvalidArgumentException(\sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); } } } $io->title('Translation Messages Extractor and Dumper'); - $io->comment(sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); + $io->comment(\sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); $io->comment('Parsing templates...'); $extractedCatalogue = $this->extractMessages($input->getArgument('locale'), $codePaths, $input->getOption('prefix')); @@ -217,8 +217,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(fn ($id) => \sprintf('%s', $id), $newKeys), + array_map(fn ($id) => \sprintf('%s', $id), array_keys($operation->getObsoleteMessages($domain))) ); $domainMessagesCount = \count($list); @@ -238,17 +238,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } - $io->section(sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); + $io->section(\sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); $io->listing($list); $extractedMessagesCount += $domainMessagesCount; } if ('xlf' === $format) { - $io->comment(sprintf('Xliff output version is %s', $xliffVersion)); + $io->comment(\sprintf('Xliff output version is %s', $xliffVersion)); } - $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); + $resultMessage = \sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); } // save the files diff --git a/Command/WorkflowDumpCommand.php b/Command/WorkflowDumpCommand.php index d732305d4..201fb8be8 100644 --- a/Command/WorkflowDumpCommand.php +++ b/Command/WorkflowDumpCommand.php @@ -75,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $workflowName = $input->getArgument('name'); if (!$this->workflows->has($workflowName)) { - throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName)); + throw new InvalidArgumentException(\sprintf('The workflow named "%s" cannot be found.', $workflowName)); } $workflow = $this->workflows->get($workflowName); $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; diff --git a/Console/Application.php b/Console/Application.php index 1c41849e7..274e7b06d 100644 --- a/Console/Application.php +++ b/Console/Application.php @@ -156,7 +156,7 @@ public function all(?string $namespace = null): array public function getLongVersion(): string { - return parent::getLongVersion().sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); + return parent::getLongVersion().\sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); } public function add(Command $command): ?Command diff --git a/Console/Descriptor/Descriptor.php b/Console/Descriptor/Descriptor.php index 8541f71bb..af5c3b10a 100644 --- a/Console/Descriptor/Descriptor.php +++ b/Console/Descriptor/Descriptor.php @@ -62,7 +62,7 @@ public function describe(OutputInterface $output, mixed $object, array $options $object instanceof Alias => $this->describeContainerAlias($object, $options), $object instanceof EventDispatcherInterface => $this->describeEventDispatcherListeners($object, $options), \is_callable($object) => $this->describeCallable($object, $options), - default => throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))), + default => throw new \InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', get_debug_type($object))), }; if ($object instanceof ContainerBuilder) { @@ -133,7 +133,7 @@ protected function formatValue(mixed $value): string } if (\is_object($value)) { - return sprintf('object(%s)', $value::class); + return \sprintf('object(%s)', $value::class); } if (\is_string($value)) { diff --git a/Console/Descriptor/JsonDescriptor.php b/Console/Descriptor/JsonDescriptor.php index 88cf4162c..5b83f0746 100644 --- a/Console/Descriptor/JsonDescriptor.php +++ b/Console/Descriptor/JsonDescriptor.php @@ -156,7 +156,7 @@ protected function describeContainerParameter(mixed $parameter, ?array $deprecat $data = [$key => $parameter]; if ($deprecation) { - $data['_deprecation'] = sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], sprintf(...\array_slice($deprecation, 2))); + $data['_deprecation'] = \sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))); } $this->writeData($data, $options); @@ -169,7 +169,7 @@ protected function describeContainerEnvVars(array $envs, array $options = []): v protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); + $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); if (!file_exists($containerDeprecationFilePath)) { throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.'); } @@ -236,7 +236,7 @@ protected function sortParameters(ParameterBag $parameters): array $deprecations = []; foreach ($deprecated as $parameter => $deprecation) { - $deprecations[$parameter] = sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], sprintf(...\array_slice($deprecation, 2))); + $deprecations[$parameter] = \sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))); } $sortedParameters['_deprecations'] = $deprecations; @@ -280,7 +280,7 @@ private function getContainerDefinitionData(Definition $definition, bool $omitTa if ($factory[0] instanceof Reference) { $data['factory_service'] = (string) $factory[0]; } elseif ($factory[0] instanceof Definition) { - $data['factory_service'] = sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured'); + $data['factory_service'] = \sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured'); } else { $data['factory_class'] = $factory[0]; } diff --git a/Console/Descriptor/MarkdownDescriptor.php b/Console/Descriptor/MarkdownDescriptor.php index 7965990bd..5203d14c3 100644 --- a/Console/Descriptor/MarkdownDescriptor.php +++ b/Console/Descriptor/MarkdownDescriptor.php @@ -40,7 +40,7 @@ protected function describeRouteCollection(RouteCollection $routes, array $optio } $this->describeRoute($route, ['name' => $name]); if (($showAliases ??= $options['show_aliases'] ?? false) && $aliases = ($reverseAliases ??= $this->getReverseAliases($routes))[$name] ?? []) { - $this->write(sprintf("- Aliases: \n%s", implode("\n", array_map(static fn (string $alias): string => sprintf(' - %s', $alias), $aliases)))); + $this->write(\sprintf("- Aliases: \n%s", implode("\n", array_map(static fn (string $alias): string => \sprintf(' - %s', $alias), $aliases)))); } } $this->write("\n"); @@ -75,11 +75,11 @@ protected function describeContainerParameters(ParameterBag $parameters, array $ $this->write("Container parameters\n====================\n"); foreach ($this->sortParameters($parameters) as $key => $value) { - $this->write(sprintf( + $this->write(\sprintf( "\n- `%s`: `%s`%s", $key, $this->formatParameter($value), - isset($deprecatedParameters[$key]) ? sprintf(' *Since %s %s: %s*', $deprecatedParameters[$key][0], $deprecatedParameters[$key][1], sprintf(...\array_slice($deprecatedParameters[$key], 2))) : '' + isset($deprecatedParameters[$key]) ? \sprintf(' *Since %s %s: %s*', $deprecatedParameters[$key][0], $deprecatedParameters[$key][1], \sprintf(...\array_slice($deprecatedParameters[$key], 2))) : '' )); } } @@ -111,13 +111,13 @@ protected function describeContainerService(object $service, array $options = [] } elseif ($service instanceof Definition) { $this->describeContainerDefinition($service, $childOptions, $container); } else { - $this->write(sprintf('**`%s`:** `%s`', $options['id'], $service::class)); + $this->write(\sprintf('**`%s`:** `%s`', $options['id'], $service::class)); } } protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); + $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); if (!file_exists($containerDeprecationFilePath)) { throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.'); } @@ -132,11 +132,11 @@ protected function describeContainerDeprecations(ContainerBuilder $container, ar $formattedLogs = []; $remainingCount = 0; foreach ($logs as $log) { - $formattedLogs[] = sprintf("- %sx: \"%s\" in %s:%s\n", $log['count'], $log['message'], $log['file'], $log['line']); + $formattedLogs[] = \sprintf("- %sx: \"%s\" in %s:%s\n", $log['count'], $log['message'], $log['file'], $log['line']); $remainingCount += $log['count']; } - $this->write(sprintf("## Remaining deprecations (%s)\n\n", $remainingCount)); + $this->write(\sprintf("## Remaining deprecations (%s)\n\n", $remainingCount)); foreach ($formattedLogs as $formattedLog) { $this->write($formattedLog); } @@ -201,7 +201,7 @@ protected function describeContainerServices(ContainerBuilder $container, array $this->write("\n\nServices\n--------\n"); foreach ($services['services'] as $id => $service) { $this->write("\n"); - $this->write(sprintf('- `%s`: `%s`', $id, $service::class)); + $this->write(\sprintf('- `%s`: `%s`', $id, $service::class)); } } } @@ -244,7 +244,7 @@ protected function describeContainerDefinition(Definition $definition, array $op if ($factory[0] instanceof Reference) { $output .= "\n".'- Factory Service: `'.$factory[0].'`'; } elseif ($factory[0] instanceof Definition) { - $output .= "\n".sprintf('- Factory Service: inline factory service (%s)', $factory[0]->getClass() ? sprintf('`%s`', $factory[0]->getClass()) : 'not configured'); + $output .= "\n".\sprintf('- Factory Service: inline factory service (%s)', $factory[0]->getClass() ? \sprintf('`%s`', $factory[0]->getClass()) : 'not configured'); } else { $output .= "\n".'- Factory Class: `'.$factory[0].'`'; } @@ -273,7 +273,7 @@ protected function describeContainerDefinition(Definition $definition, array $op $inEdges = null !== $container && isset($options['id']) ? $this->getServiceEdges($container, $options['id']) : []; $output .= "\n".'- Usages: '.($inEdges ? implode(', ', $inEdges) : 'none'); - $this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output); + $this->write(isset($options['id']) ? \sprintf("### %s\n\n%s\n", $options['id'], $output) : $output); } protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void @@ -287,7 +287,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], ?Co return; } - $this->write(sprintf("### %s\n\n%s\n", $options['id'], $output)); + $this->write(\sprintf("### %s\n\n%s\n", $options['id'], $output)); if (!$container) { return; @@ -300,7 +300,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], ?Co protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void { if (isset($options['parameter'])) { - $this->write(sprintf("%s\n%s\n\n%s%s", $options['parameter'], str_repeat('=', \strlen($options['parameter'])), $this->formatParameter($parameter), $deprecation ? sprintf("\n\n*Since %s %s: %s*", $deprecation[0], $deprecation[1], sprintf(...\array_slice($deprecation, 2))) : '')); + $this->write(\sprintf("%s\n%s\n\n%s%s", $options['parameter'], str_repeat('=', \strlen($options['parameter'])), $this->formatParameter($parameter), $deprecation ? \sprintf("\n\n*Since %s %s: %s*", $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))) : '')); } else { $this->write($parameter); } @@ -319,35 +319,35 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev $title = 'Registered listeners'; if (null !== $dispatcherServiceName) { - $title .= sprintf(' of event dispatcher "%s"', $dispatcherServiceName); + $title .= \sprintf(' of event dispatcher "%s"', $dispatcherServiceName); } if (null !== $event) { - $title .= sprintf(' for event `%s` ordered by descending priority', $event); + $title .= \sprintf(' for event `%s` ordered by descending priority', $event); $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(); } - $this->write(sprintf('# %s', $title)."\n"); + $this->write(\sprintf('# %s', $title)."\n"); if (null !== $event) { foreach ($registeredListeners as $order => $listener) { - $this->write("\n".sprintf('## Listener %d', $order + 1)."\n"); + $this->write("\n".\sprintf('## Listener %d', $order + 1)."\n"); $this->describeCallable($listener); - $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener))."\n"); + $this->write(\sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener))."\n"); } } else { ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { - $this->write("\n".sprintf('## %s', $eventListened)."\n"); + $this->write("\n".\sprintf('## %s', $eventListened)."\n"); foreach ($eventListeners as $order => $eventListener) { - $this->write("\n".sprintf('### Listener %d', $order + 1)."\n"); + $this->write("\n".\sprintf('### Listener %d', $order + 1)."\n"); $this->describeCallable($eventListener); - $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener))."\n"); + $this->write(\sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener))."\n"); } } } @@ -361,16 +361,16 @@ protected function describeCallable(mixed $callable, array $options = []): void $string .= "\n- Type: `function`"; if (\is_object($callable[0])) { - $string .= "\n".sprintf('- Name: `%s`', $callable[1]); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]::class); + $string .= "\n".\sprintf('- Name: `%s`', $callable[1]); + $string .= "\n".\sprintf('- Class: `%s`', $callable[0]::class); } else { if (!str_starts_with($callable[1], 'parent::')) { - $string .= "\n".sprintf('- Name: `%s`', $callable[1]); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]); + $string .= "\n".\sprintf('- Name: `%s`', $callable[1]); + $string .= "\n".\sprintf('- Class: `%s`', $callable[0]); $string .= "\n- Static: yes"; } else { - $string .= "\n".sprintf('- Name: `%s`', substr($callable[1], 8)); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]); + $string .= "\n".\sprintf('- Name: `%s`', substr($callable[1], 8)); + $string .= "\n".\sprintf('- Class: `%s`', $callable[0]); $string .= "\n- Static: yes"; $string .= "\n- Parent: yes"; } @@ -385,12 +385,12 @@ protected function describeCallable(mixed $callable, array $options = []): void $string .= "\n- Type: `function`"; if (!str_contains($callable, '::')) { - $string .= "\n".sprintf('- Name: `%s`', $callable); + $string .= "\n".\sprintf('- Name: `%s`', $callable); } else { $callableParts = explode('::', $callable); - $string .= "\n".sprintf('- Name: `%s`', $callableParts[1]); - $string .= "\n".sprintf('- Class: `%s`', $callableParts[0]); + $string .= "\n".\sprintf('- Name: `%s`', $callableParts[1]); + $string .= "\n".\sprintf('- Class: `%s`', $callableParts[0]); $string .= "\n- Static: yes"; } @@ -408,10 +408,10 @@ protected function describeCallable(mixed $callable, array $options = []): void return; } - $string .= "\n".sprintf('- Name: `%s`', $r->name); + $string .= "\n".\sprintf('- Name: `%s`', $r->name); if ($class = $r->getClosureCalledClass()) { - $string .= "\n".sprintf('- Class: `%s`', $class->name); + $string .= "\n".\sprintf('- Class: `%s`', $class->name); if (!$r->getClosureThis()) { $string .= "\n- Static: yes"; } @@ -424,7 +424,7 @@ protected function describeCallable(mixed $callable, array $options = []): void if (method_exists($callable, '__invoke')) { $string .= "\n- Type: `object`"; - $string .= "\n".sprintf('- Name: `%s`', $callable::class); + $string .= "\n".\sprintf('- Name: `%s`', $callable::class); $this->write($string."\n"); diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index d728128ce..6ee8b04a1 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -131,7 +131,7 @@ protected function describeContainerParameters(ParameterBag $parameters, array $ if (isset($deprecatedParameters[$parameter])) { $tableRows[] = [new TableCell( - sprintf('(Since %s %s: %s)', $deprecatedParameters[$parameter][0], $deprecatedParameters[$parameter][1], sprintf(...\array_slice($deprecatedParameters[$parameter], 2))), + \sprintf('(Since %s %s: %s)', $deprecatedParameters[$parameter][0], $deprecatedParameters[$parameter][1], \sprintf(...\array_slice($deprecatedParameters[$parameter], 2))), ['colspan' => 2] )]; } @@ -152,7 +152,7 @@ protected function describeContainerTags(ContainerBuilder $container, array $opt } foreach ($this->findDefinitionsByTag($container, $showHidden) as $tag => $definitions) { - $options['output']->section(sprintf('"%s" tag', $tag)); + $options['output']->section(\sprintf('"%s" tag', $tag)); $options['output']->listing(array_keys($definitions)); } } @@ -168,7 +168,7 @@ protected function describeContainerService(object $service, array $options = [] } elseif ($service instanceof Definition) { $this->describeContainerDefinition($service, $options, $container); } else { - $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); + $options['output']->title(\sprintf('Information for Service "%s"', $options['id'])); $options['output']->table( ['Service ID', 'Class'], [ @@ -190,7 +190,7 @@ protected function describeContainerServices(ContainerBuilder $container, array } if ($showTag) { - $title .= sprintf(' Tagged with "%s" Tag', $options['tag']); + $title .= \sprintf(' Tagged with "%s" Tag', $options['tag']); } $options['output']->title($title); @@ -247,7 +247,7 @@ protected function describeContainerServices(ContainerBuilder $container, array foreach ($serviceIds as $serviceId) { $definition = $this->resolveServiceDefinition($container, $serviceId); - $styledServiceId = $rawOutput ? $serviceId : sprintf('%s', OutputFormatter::escape($serviceId)); + $styledServiceId = $rawOutput ? $serviceId : \sprintf('%s', OutputFormatter::escape($serviceId)); if ($definition instanceof Definition) { if ($showTag) { foreach ($this->sortByPriority($definition->getTag($showTag)) as $key => $tag) { @@ -270,7 +270,7 @@ protected function describeContainerServices(ContainerBuilder $container, array } } elseif ($definition instanceof Alias) { $alias = $definition; - $tableRows[] = array_merge([$styledServiceId, sprintf('alias for "%s"', $alias)], $tagsCount ? array_fill(0, $tagsCount, '') : []); + $tableRows[] = array_merge([$styledServiceId, \sprintf('alias for "%s"', $alias)], $tagsCount ? array_fill(0, $tagsCount, '') : []); } else { $tableRows[] = array_merge([$styledServiceId, $definition::class], $tagsCount ? array_fill(0, $tagsCount, '') : []); } @@ -282,7 +282,7 @@ protected function describeContainerServices(ContainerBuilder $container, array protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void { if (isset($options['id'])) { - $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); + $options['output']->title(\sprintf('Information for Service "%s"', $options['id'])); } if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { @@ -299,13 +299,13 @@ protected function describeContainerDefinition(Definition $definition, array $op $tagInformation = []; foreach ($tags as $tagName => $tagData) { foreach ($tagData as $tagParameters) { - $parameters = array_map(fn ($key, $value) => sprintf('%s: %s', $key, \is_array($value) ? $this->formatParameter($value) : $value), array_keys($tagParameters), array_values($tagParameters)); + $parameters = array_map(fn ($key, $value) => \sprintf('%s: %s', $key, \is_array($value) ? $this->formatParameter($value) : $value), array_keys($tagParameters), array_values($tagParameters)); $parameters = implode(', ', $parameters); if ('' === $parameters) { - $tagInformation[] = sprintf('%s', $tagName); + $tagInformation[] = \sprintf('%s', $tagName); } else { - $tagInformation[] = sprintf('%s (%s)', $tagName, $parameters); + $tagInformation[] = \sprintf('%s (%s)', $tagName, $parameters); } } } @@ -341,7 +341,7 @@ protected function describeContainerDefinition(Definition $definition, array $op if ($factory[0] instanceof Reference) { $tableRows[] = ['Factory Service', $factory[0]]; } elseif ($factory[0] instanceof Definition) { - $tableRows[] = ['Factory Service', sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured')]; + $tableRows[] = ['Factory Service', \sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured')]; } else { $tableRows[] = ['Factory Class', $factory[0]]; } @@ -359,27 +359,27 @@ protected function describeContainerDefinition(Definition $definition, array $op $argument = $argument->getValues()[0]; } if ($argument instanceof Reference) { - $argumentsInformation[] = sprintf('Service(%s)', (string) $argument); + $argumentsInformation[] = \sprintf('Service(%s)', (string) $argument); } elseif ($argument instanceof IteratorArgument) { if ($argument instanceof TaggedIteratorArgument) { - $argumentsInformation[] = sprintf('Tagged Iterator for "%s"%s', $argument->getTag(), $options['is_debug'] ? '' : sprintf(' (%d element(s))', \count($argument->getValues()))); + $argumentsInformation[] = \sprintf('Tagged Iterator for "%s"%s', $argument->getTag(), $options['is_debug'] ? '' : \sprintf(' (%d element(s))', \count($argument->getValues()))); } else { - $argumentsInformation[] = sprintf('Iterator (%d element(s))', \count($argument->getValues())); + $argumentsInformation[] = \sprintf('Iterator (%d element(s))', \count($argument->getValues())); } foreach ($argument->getValues() as $ref) { - $argumentsInformation[] = sprintf('- Service(%s)', $ref); + $argumentsInformation[] = \sprintf('- Service(%s)', $ref); } } elseif ($argument instanceof ServiceLocatorArgument) { - $argumentsInformation[] = sprintf('Service locator (%d element(s))', \count($argument->getValues())); + $argumentsInformation[] = \sprintf('Service locator (%d element(s))', \count($argument->getValues())); } elseif ($argument instanceof Definition) { $argumentsInformation[] = 'Inlined Service'; } elseif ($argument instanceof \UnitEnum) { $argumentsInformation[] = ltrim(var_export($argument, true), '\\'); } elseif ($argument instanceof AbstractArgument) { - $argumentsInformation[] = sprintf('Abstract argument (%s)', $argument->getText()); + $argumentsInformation[] = \sprintf('Abstract argument (%s)', $argument->getText()); } else { - $argumentsInformation[] = \is_array($argument) ? sprintf('Array (%d element(s))', \count($argument)) : $argument; + $argumentsInformation[] = \is_array($argument) ? \sprintf('Array (%d element(s))', \count($argument)) : $argument; } } @@ -394,7 +394,7 @@ protected function describeContainerDefinition(Definition $definition, array $op protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); + $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); if (!file_exists($containerDeprecationFilePath)) { $options['output']->warning('The deprecation file does not exist, please try warming the cache first.'); @@ -411,19 +411,19 @@ protected function describeContainerDeprecations(ContainerBuilder $container, ar $formattedLogs = []; $remainingCount = 0; foreach ($logs as $log) { - $formattedLogs[] = sprintf("%sx: %s\n in %s:%s", $log['count'], $log['message'], $log['file'], $log['line']); + $formattedLogs[] = \sprintf("%sx: %s\n in %s:%s", $log['count'], $log['message'], $log['file'], $log['line']); $remainingCount += $log['count']; } - $options['output']->title(sprintf('Remaining deprecations (%s)', $remainingCount)); + $options['output']->title(\sprintf('Remaining deprecations (%s)', $remainingCount)); $options['output']->listing($formattedLogs); } protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void { if ($alias->isPublic() && !$alias->isPrivate()) { - $options['output']->comment(sprintf('This service is a public alias for the service %s', (string) $alias)); + $options['output']->comment(\sprintf('This service is a public alias for the service %s', (string) $alias)); } else { - $options['output']->comment(sprintf('This service is a private alias for the service %s', (string) $alias)); + $options['output']->comment(\sprintf('This service is a private alias for the service %s', (string) $alias)); } if (!$container) { @@ -442,7 +442,7 @@ protected function describeContainerParameter(mixed $parameter, ?array $deprecat if ($deprecation) { $rows[] = [new TableCell( - sprintf('(Since %s %s: %s)', $deprecation[0], $deprecation[1], sprintf(...\array_slice($deprecation, 2))), + \sprintf('(Since %s %s: %s)', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2))), ['colspan' => 2] )]; } @@ -520,11 +520,11 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev $title = 'Registered Listeners'; if (null !== $dispatcherServiceName) { - $title .= sprintf(' of Event Dispatcher "%s"', $dispatcherServiceName); + $title .= \sprintf(' of Event Dispatcher "%s"', $dispatcherServiceName); } if (null !== $event) { - $title .= sprintf(' for "%s" Event', $event); + $title .= \sprintf(' for "%s" Event', $event); $registeredListeners = $eventDispatcher->getListeners($event); } else { $title .= ' Grouped by Event'; @@ -538,7 +538,7 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev } else { ksort($registeredListeners); foreach ($registeredListeners as $eventListened => $eventListeners) { - $options['output']->section(sprintf('"%s" event', $eventListened)); + $options['output']->section(\sprintf('"%s" event', $eventListened)); $this->renderEventListenerTable($eventDispatcher, $eventListened, $eventListeners, $options['output']); } } @@ -555,7 +555,7 @@ private function renderEventListenerTable(EventDispatcherInterface $eventDispatc $tableRows = []; foreach ($eventListeners as $order => $listener) { - $tableRows[] = [sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)]; + $tableRows[] = [\sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)]; } $io->table($tableHeaders, $tableRows); @@ -571,7 +571,7 @@ private function formatRouterConfig(array $config): string $configAsString = ''; foreach ($config as $key => $value) { - $configAsString .= sprintf("\n%s: %s", $key, $this->formatValue($value)); + $configAsString .= \sprintf("\n%s: %s", $key, $this->formatValue($value)); } return trim($configAsString); @@ -625,7 +625,7 @@ private function formatControllerLink(mixed $controller, string $anchorText, ?ca $fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); if ($fileLink) { - return sprintf('%s', $fileLink, $anchorText); + return \sprintf('%s', $fileLink, $anchorText); } return $anchorText; @@ -635,14 +635,14 @@ private function formatCallable(mixed $callable): string { if (\is_array($callable)) { if (\is_object($callable[0])) { - return sprintf('%s::%s()', $callable[0]::class, $callable[1]); + return \sprintf('%s::%s()', $callable[0]::class, $callable[1]); } - return sprintf('%s::%s()', $callable[0], $callable[1]); + return \sprintf('%s::%s()', $callable[0], $callable[1]); } if (\is_string($callable)) { - return sprintf('%s()', $callable); + return \sprintf('%s()', $callable); } if ($callable instanceof \Closure) { @@ -651,14 +651,14 @@ private function formatCallable(mixed $callable): string return 'Closure()'; } if ($class = $r->getClosureCalledClass()) { - return sprintf('%s::%s()', $class->name, $r->name); + return \sprintf('%s::%s()', $class->name, $r->name); } return $r->name.'()'; } if (method_exists($callable, '__invoke')) { - return sprintf('%s::__invoke()', $callable::class); + return \sprintf('%s::__invoke()', $callable::class); } throw new \InvalidArgumentException('Callable is not describable.'); diff --git a/Console/Descriptor/XmlDescriptor.php b/Console/Descriptor/XmlDescriptor.php index c52b19667..dd2744f80 100644 --- a/Console/Descriptor/XmlDescriptor.php +++ b/Console/Descriptor/XmlDescriptor.php @@ -110,7 +110,7 @@ protected function describeContainerEnvVars(array $envs, array $options = []): v protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); + $containerDeprecationFilePath = \sprintf('%s/%sDeprecations.log', $container->getParameter('kernel.build_dir'), $container->getParameter('kernel.container_class')); if (!file_exists($containerDeprecationFilePath)) { throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.'); } @@ -243,7 +243,7 @@ private function getContainerParametersDocument(ParameterBag $parameters): \DOMD $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); if (isset($deprecatedParameters[$key])) { - $parameterXML->setAttribute('deprecated', sprintf('Since %s %s: %s', $deprecatedParameters[$key][0], $deprecatedParameters[$key][1], sprintf(...\array_slice($deprecatedParameters[$key], 2)))); + $parameterXML->setAttribute('deprecated', \sprintf('Since %s %s: %s', $deprecatedParameters[$key][0], $deprecatedParameters[$key][1], \sprintf(...\array_slice($deprecatedParameters[$key], 2)))); } } @@ -341,7 +341,7 @@ private function getContainerDefinitionDocument(Definition $definition, ?string if ($factory[0] instanceof Reference) { $factoryXML->setAttribute('service', (string) $factory[0]); } elseif ($factory[0] instanceof Definition) { - $factoryXML->setAttribute('service', sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'not configured')); + $factoryXML->setAttribute('service', \sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'not configured')); } else { $factoryXML->setAttribute('class', $factory[0]); } @@ -490,7 +490,7 @@ private function getContainerParameterDocument(mixed $parameter, ?array $depreca $parameterXML->setAttribute('key', $options['parameter']); if ($deprecation) { - $parameterXML->setAttribute('deprecated', sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], sprintf(...\array_slice($deprecation, 2)))); + $parameterXML->setAttribute('deprecated', \sprintf('Since %s %s: %s', $deprecation[0], $deprecation[1], \sprintf(...\array_slice($deprecation, 2)))); } } diff --git a/Controller/AbstractController.php b/Controller/AbstractController.php index f0c1d98ee..af453619b 100644 --- a/Controller/AbstractController.php +++ b/Controller/AbstractController.php @@ -72,7 +72,7 @@ public function setContainer(ContainerInterface $container): ?ContainerInterface protected function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null { if (!$this->container->has('parameter_bag')) { - throw new ServiceNotFoundException('parameter_bag.', null, null, [], sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class)); + throw new ServiceNotFoundException('parameter_bag.', null, null, [], \sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class)); } return $this->container->get('parameter_bag')->get($name); @@ -182,7 +182,7 @@ protected function addFlash(string $type, mixed $message): void } if (!$session instanceof FlashBagAwareSessionInterface) { - throw new \LogicException(sprintf('You cannot use the addFlash method because class "%s" doesn\'t implement "%s".', get_debug_type($session), FlashBagAwareSessionInterface::class)); + throw new \LogicException(\sprintf('You cannot use the addFlash method because class "%s" doesn\'t implement "%s".', get_debug_type($session), FlashBagAwareSessionInterface::class)); } $session->getFlashBag()->add($type, $message); @@ -415,7 +415,7 @@ protected function sendEarlyHints(iterable $links = [], ?Response $response = nu private function doRenderView(string $view, ?string $block, array $parameters, string $method): string { if (!$this->container->has('twig')) { - throw new \LogicException(sprintf('You cannot use the "%s" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".', $method)); + throw new \LogicException(\sprintf('You cannot use the "%s" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".', $method)); } foreach ($parameters as $k => $v) { diff --git a/Controller/ControllerResolver.php b/Controller/ControllerResolver.php index af8b49429..269709963 100644 --- a/Controller/ControllerResolver.php +++ b/Controller/ControllerResolver.php @@ -26,7 +26,7 @@ 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)); + throw new \LogicException(\sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class)); } else { $controller->setContainer($previousContainer); } diff --git a/Controller/RedirectController.php b/Controller/RedirectController.php index 1001fad63..65d2be121 100644 --- a/Controller/RedirectController.php +++ b/Controller/RedirectController.php @@ -168,7 +168,7 @@ public function __invoke(Request $request): Response if (\array_key_exists('route', $p)) { if (\array_key_exists('path', $p)) { - throw new \RuntimeException(sprintf('Ambiguous redirection settings, use the "path" or "route" parameter, not both: "%s" and "%s" found respectively in "%s" routing configuration.', $p['path'], $p['route'], $request->attributes->get('_route'))); + throw new \RuntimeException(\sprintf('Ambiguous redirection settings, use the "path" or "route" parameter, not both: "%s" and "%s" found respectively in "%s" routing configuration.', $p['path'], $p['route'], $request->attributes->get('_route'))); } return $this->redirectAction($request, $p['route'], $p['permanent'] ?? false, $p['ignoreAttributes'] ?? false, $p['keepRequestMethod'] ?? false, $p['keepQueryParams'] ?? false); @@ -178,6 +178,6 @@ public function __invoke(Request $request): Response return $this->urlRedirectAction($request, $p['path'], $p['permanent'] ?? false, $p['scheme'] ?? null, $p['httpPort'] ?? null, $p['httpsPort'] ?? null, $p['keepRequestMethod'] ?? false); } - throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route'))); + throw new \RuntimeException(\sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route'))); } } diff --git a/DependencyInjection/Compiler/ProfilerPass.php b/DependencyInjection/Compiler/ProfilerPass.php index 05fe0a451..4da07e64a 100644 --- a/DependencyInjection/Compiler/ProfilerPass.php +++ b/DependencyInjection/Compiler/ProfilerPass.php @@ -42,7 +42,7 @@ public function process(ContainerBuilder $container): void if (isset($attributes[0]['template']) || is_subclass_of($collectorClass, TemplateAwareDataCollectorInterface::class)) { $idForTemplate = $attributes[0]['id'] ?? $collectorClass; if (!$idForTemplate) { - throw new InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template.', $id)); + throw new InvalidArgumentException(\sprintf('Data collector service "%s" must have an id attribute in order to specify a template.', $id)); } $template = [$idForTemplate, $attributes[0]['template'] ?? $collectorClass::getTemplate()]; } diff --git a/DependencyInjection/Compiler/UnusedTagsPass.php b/DependencyInjection/Compiler/UnusedTagsPass.php index a2a141afb..ae2523e51 100644 --- a/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/DependencyInjection/Compiler/UnusedTagsPass.php @@ -128,9 +128,9 @@ public function process(ContainerBuilder $container): void } $services = array_keys($container->findTaggedServiceIds($tag)); - $message = sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services)); + $message = \sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services)); if ($candidates) { - $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates)); + $message .= \sprintf(' Did you mean "%s"?', implode('", "', $candidates)); } $container->log($this, $message); diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 92c20d139..d5137dc2b 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -361,7 +361,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void foreach ($workflows as $key => $workflow) { if (isset($workflow['enabled']) && false === $workflow['enabled']) { - throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $key)); + throw new LogicException(\sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $key)); } unset($workflows[$key]['enabled']); @@ -1328,7 +1328,7 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode): void ->info('The level of log message. Null to let Symfony decide.') ->validate() ->ifTrue(fn ($v) => null !== $v && !\in_array($v, $logLevels, true)) - ->thenInvalid(sprintf('The log level is not valid. Pick one among "%s".', implode('", "', $logLevels))) + ->thenInvalid(\sprintf('The log level is not valid. Pick one among "%s".', implode('", "', $logLevels))) ->end() ->defaultNull() ->end() @@ -1496,7 +1496,7 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $en ->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']))))) + ->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']))))) ->end() ->children() ->arrayNode('routing') diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 942358181..fd6cb4b83 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -669,7 +669,7 @@ public function load(array $configs, ContainerBuilder $container): void $tagAttributes = get_object_vars($attribute); if ($reflector instanceof \ReflectionMethod) { if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('AsEventListener attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); + throw new LogicException(\sprintf('AsEventListener attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); } $tagAttributes['method'] = $reflector->getName(); } @@ -687,7 +687,7 @@ public function load(array $configs, ContainerBuilder $container): void unset($tagAttributes['fromTransport']); if ($reflector instanceof \ReflectionMethod) { if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('AsMessageHandler attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); + throw new LogicException(\sprintf('AsMessageHandler attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); } $tagAttributes['method'] = $reflector->getName(); } @@ -711,7 +711,7 @@ static function (ChildDefinition $definition, AsPeriodicTask|AsCronTask $attribu ]; if ($reflector instanceof \ReflectionMethod) { if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('"%s" attribute cannot declare a method on "%s::%s()".', $attribute::class, $reflector->class, $reflector->name)); + throw new LogicException(\sprintf('"%s" attribute cannot declare a method on "%s::%s()".', $attribute::class, $reflector->class, $reflector->name)); } $tagAttributes['method'] = $reflector->getName(); } @@ -897,7 +897,7 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ // Choose storage class based on the DSN [$class] = explode(':', $config['dsn'], 2); if ('file' !== $class) { - throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class)); + throw new \LogicException(\sprintf('Driver "%s" is not supported for the profiler.', $class)); } $container->setParameter('profiler.storage.dsn', $config['dsn']); @@ -936,7 +936,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ foreach ($config['workflows'] as $name => $workflow) { $type = $workflow['type']; - $workflowId = sprintf('%s.%s', $type, $name); + $workflowId = \sprintf('%s.%s', $type, $name); // Process Metadata (workflow + places (transition is done in the "create transition" block)) $metadataStoreDefinition = new Definition(Workflow\Metadata\InMemoryMetadataStore::class, [[], [], null]); @@ -962,14 +962,14 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ foreach ($workflow['transitions'] as $transition) { if ('workflow' === $type) { $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $transition['from'], $transition['to']]); - $transitionId = sprintf('.%s.transition.%s', $workflowId, $transitionCounter++); + $transitionId = \sprintf('.%s.transition.%s', $workflowId, $transitionCounter++); $container->setDefinition($transitionId, $transitionDefinition); $transitions[] = new Reference($transitionId); if (isset($transition['guard'])) { $configuration = new Definition(Workflow\EventListener\GuardExpression::class); $configuration->addArgument(new Reference($transitionId)); $configuration->addArgument($transition['guard']); - $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); + $eventName = \sprintf('workflow.%s.guard.%s', $name, $transition['name']); $guardsConfiguration[$eventName][] = $configuration; } if ($transition['metadata']) { @@ -982,14 +982,14 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ foreach ($transition['from'] as $from) { foreach ($transition['to'] as $to) { $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $from, $to]); - $transitionId = sprintf('.%s.transition.%s', $workflowId, $transitionCounter++); + $transitionId = \sprintf('.%s.transition.%s', $workflowId, $transitionCounter++); $container->setDefinition($transitionId, $transitionDefinition); $transitions[] = new Reference($transitionId); if (isset($transition['guard'])) { $configuration = new Definition(Workflow\EventListener\GuardExpression::class); $configuration->addArgument(new Reference($transitionId)); $configuration->addArgument($transition['guard']); - $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); + $eventName = \sprintf('workflow.%s.guard.%s', $name, $transition['name']); $guardsConfiguration[$eventName][] = $configuration; } if ($transition['metadata']) { @@ -1003,7 +1003,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ } } $metadataStoreDefinition->replaceArgument(2, $transitionsMetadataDefinition); - $container->setDefinition(sprintf('%s.metadata_store', $workflowId), $metadataStoreDefinition); + $container->setDefinition(\sprintf('%s.metadata_store', $workflowId), $metadataStoreDefinition); // Create places $places = array_column($workflow['places'], 'name'); @@ -1014,7 +1014,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $definitionDefinition->addArgument($places); $definitionDefinition->addArgument($transitions); $definitionDefinition->addArgument($initialMarking); - $definitionDefinition->addArgument(new Reference(sprintf('%s.metadata_store', $workflowId))); + $definitionDefinition->addArgument(new Reference(\sprintf('%s.metadata_store', $workflowId))); // Create MarkingStore $markingStoreDefinition = null; @@ -1029,8 +1029,8 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ } // Create Workflow - $workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type)); - $workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId))); + $workflowDefinition = new ChildDefinition(\sprintf('%s.abstract', $type)); + $workflowDefinition->replaceArgument(0, new Reference(\sprintf('%s.definition', $workflowId))); $workflowDefinition->replaceArgument(1, $markingStoreDefinition); $workflowDefinition->replaceArgument(3, $name); $workflowDefinition->replaceArgument(4, $workflow['events_to_dispatch']); @@ -1044,7 +1044,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ // Store to container $container->setDefinition($workflowId, $workflowDefinition); - $container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition); + $container->setDefinition(\sprintf('%s.definition', $workflowId), $definitionDefinition); $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name.'.'.$type); $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name); @@ -1073,11 +1073,11 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ if ($workflow['audit_trail']['enabled']) { $listener = new Definition(Workflow\EventListener\AuditTrailListener::class); $listener->addTag('monolog.logger', ['channel' => 'workflow']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.leave', $name), 'method' => 'onLeave']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.transition', $name), 'method' => 'onTransition']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.enter', $name), 'method' => 'onEnter']); + $listener->addTag('kernel.event_listener', ['event' => \sprintf('workflow.%s.leave', $name), 'method' => 'onLeave']); + $listener->addTag('kernel.event_listener', ['event' => \sprintf('workflow.%s.transition', $name), 'method' => 'onTransition']); + $listener->addTag('kernel.event_listener', ['event' => \sprintf('workflow.%s.enter', $name), 'method' => 'onEnter']); $listener->addArgument(new Reference('logger')); - $container->setDefinition(sprintf('.%s.listener.audit_trail', $workflowId), $listener); + $container->setDefinition(\sprintf('.%s.listener.audit_trail', $workflowId), $listener); } // Add Guard Listener @@ -1105,7 +1105,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $guard->addTag('kernel.event_listener', ['event' => $eventName, 'method' => 'onTransition']); } - $container->setDefinition(sprintf('.%s.listener.guard', $workflowId), $guard); + $container->setDefinition(\sprintf('.%s.listener.guard', $workflowId), $guard); $container->setParameter('workflow.has_guard_listeners', true); } } @@ -1307,7 +1307,7 @@ private function registerAssetMapperConfiguration(array $config, ContainerBuilde $paths = $config['paths']; foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { if ($container->fileExists($dir = $bundle['path'].'/Resources/public') || $container->fileExists($dir = $bundle['path'].'/public')) { - $paths[$dir] = sprintf('bundles/%s', preg_replace('/bundle$/', '', strtolower($name))); + $paths[$dir] = \sprintf('bundles/%s', preg_replace('/bundle$/', '', strtolower($name))); } } $excludedPathPatterns = []; @@ -1484,7 +1484,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder if ($container->fileExists($dir)) { $dirs[] = $transPaths[] = $dir; } else { - throw new \UnexpectedValueException(sprintf('"%s" defined in translator.paths does not exist or is not a directory.', $dir)); + throw new \UnexpectedValueException(\sprintf('"%s" defined in translator.paths does not exist or is not a directory.', $dir)); } } @@ -1568,7 +1568,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder foreach ($classToServices as $class => $service) { $package = substr($service, \strlen('translation.provider_factory.')); - if (!$container->hasDefinition('http_client') || !ContainerBuilder::willBeAvailable(sprintf('symfony/%s-translation-provider', $package), $class, $parentPackages)) { + if (!$container->hasDefinition('http_client') || !ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-translation-provider', $package), $class, $parentPackages)) { $container->removeDefinition($service); } } @@ -1726,11 +1726,11 @@ private function registerMappingFilesFromConfig(ContainerBuilder $container, arr $container->addResource(new DirectoryResource($path, '/^$/')); } elseif ($container->fileExists($path, false)) { if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) { - throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path)); + throw new \RuntimeException(\sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path)); } $fileRecorder($matches[1], $path); } else { - throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path)); + throw new \RuntimeException(\sprintf('Could not open file or directory "%s".', $path)); } } } @@ -1790,7 +1790,7 @@ private function registerSecretsConfiguration(array $config, ContainerBuilder $c if ($config['decryption_env_var']) { if (!preg_match('/^(?:[-.\w\\\\]*+:)*+\w++$/', $config['decryption_env_var'])) { - throw new InvalidArgumentException(sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var'])); + throw new InvalidArgumentException(\sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var'])); } if (ContainerBuilder::willBeAvailable('symfony/string', LazyString::class, ['symfony/framework-bundle'])) { @@ -2173,7 +2173,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $failureTransports = []; if ($config['failure_transport']) { if (!isset($config['transports'][$config['failure_transport']])) { - throw new LogicException(sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $config['failure_transport'])); + throw new LogicException(\sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $config['failure_transport'])); } $container->setAlias('messenger.failure_transports.default', 'messenger.transport.'.$config['failure_transport']); @@ -2209,7 +2209,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder if (null !== $transport['retry_strategy']['service']) { $transportRetryReferences[$name] = new Reference($transport['retry_strategy']['service']); } else { - $retryServiceId = sprintf('messenger.retry.multiplier_retry_strategy.%s', $name); + $retryServiceId = \sprintf('messenger.retry.multiplier_retry_strategy.%s', $name); $retryDefinition = new ChildDefinition('messenger.retry.abstract_multiplier_retry_strategy'); $retryDefinition ->replaceArgument(0, $transport['retry_strategy']['max_retries']) @@ -2244,7 +2244,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder foreach ($config['transports'] as $name => $transport) { if ($transport['failure_transport']) { if (!isset($senderReferences[$transport['failure_transport']])) { - throw new LogicException(sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $transport['failure_transport'])); + throw new LogicException(\sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $transport['failure_transport'])); } } } @@ -2255,16 +2255,16 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder foreach ($config['routing'] as $message => $messageConfiguration) { if ('*' !== $message && !class_exists($message) && !interface_exists($message, false) && !preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++\*$/', $message)) { if (str_contains($message, '*')) { - throw new LogicException(sprintf('Invalid Messenger routing configuration: invalid namespace "%s" wildcard.', $message)); + throw new LogicException(\sprintf('Invalid Messenger routing configuration: invalid namespace "%s" wildcard.', $message)); } - throw new LogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message)); + throw new LogicException(\sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message)); } // make sure senderAliases contains all senders foreach ($messageConfiguration['senders'] as $sender) { if (!isset($senderReferences[$sender])) { - throw new LogicException(sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender)); + throw new LogicException(\sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender)); } } @@ -2471,7 +2471,7 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder foreach ($config['scoped_clients'] as $name => $scopeConfig) { if ($container->has($name)) { - throw new InvalidArgumentException(sprintf('Invalid scope name: "%s" is reserved.', $name)); + throw new InvalidArgumentException(\sprintf('Invalid scope name: "%s" is reserved.', $name)); } $scope = $scopeConfig['scope'] ?? null; @@ -2632,7 +2632,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co 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'])) { + if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) { $container->removeDefinition($service); } } @@ -2651,7 +2651,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co 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'])) { + if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) { $container->removeDefinition($service); } } @@ -2835,7 +2835,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ foreach ($classToServices as $class => $service) { $package = substr($service, \strlen('notifier.transport_factory.')); - if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-notifier', $package), $class, $parentPackages)) { + if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-notifier', $package), $class, $parentPackages)) { $container->removeDefinition($service); } } @@ -2891,7 +2891,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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'])) { + if (!ContainerBuilder::willBeAvailable(\sprintf('symfony/%s-notifier', $package), $class, ['symfony/framework-bundle', 'symfony/notifier'])) { $container->removeDefinition($service); } } @@ -2941,11 +2941,11 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde if (null !== $limiterConfig['lock_factory']) { if (!interface_exists(LockInterface::class)) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name)); + throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name)); } if (!$this->isInitializedConfigEnabled('lock')) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be configured.', $name)); + throw new LogicException(\sprintf('Rate limiter "%s" requires the Lock component to be configured.', $name)); } $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory'])); @@ -3111,7 +3111,7 @@ private function isInitializedConfigEnabled(string $path): bool return $this->configsEnabled[$path]; } - throw new LogicException(sprintf('Can not read config enabled at "%s" because it has not been initialized.', $path)); + throw new LogicException(\sprintf('Can not read config enabled at "%s" because it has not been initialized.', $path)); } private function readConfigEnabled(string $path, ContainerBuilder $container, array $config): bool diff --git a/EventListener/ConsoleProfilerListener.php b/EventListener/ConsoleProfilerListener.php index 7bf23f04c..3df9c61b9 100644 --- a/EventListener/ConsoleProfilerListener.php +++ b/EventListener/ConsoleProfilerListener.php @@ -142,7 +142,7 @@ public function profile(ConsoleTerminateEvent $event): void if ($this->urlGenerator && $output) { $token = $p->getToken(); - $output->writeln(sprintf( + $output->writeln(\sprintf( 'See profile %s', $this->urlGenerator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL), $token diff --git a/EventListener/SuggestMissingPackageSubscriber.php b/EventListener/SuggestMissingPackageSubscriber.php index d7bdc8e66..a5a0d5d63 100644 --- a/EventListener/SuggestMissingPackageSubscriber.php +++ b/EventListener/SuggestMissingPackageSubscriber.php @@ -66,7 +66,7 @@ public function onConsoleError(ConsoleErrorEvent $event): void return; } - $message = sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); + $message = \sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); $event->setError(new CommandNotFoundException($message)); } diff --git a/KernelBrowser.php b/KernelBrowser.php index e06b9a056..6bc82b97c 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -103,11 +103,11 @@ public function enableReboot(): void public function loginUser(object $user, string $firewallContext = 'main', array $tokenAttributes = []): static { if (!interface_exists(UserInterface::class)) { - throw new \LogicException(sprintf('"%s" requires symfony/security-core to be installed. Try running "composer require symfony/security-core".', __METHOD__)); + throw new \LogicException(\sprintf('"%s" requires symfony/security-core to be installed. Try running "composer require symfony/security-core".', __METHOD__)); } if (!$user instanceof UserInterface) { - throw new \LogicException(sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, UserInterface::class, get_debug_type($user))); + throw new \LogicException(\sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, UserInterface::class, get_debug_type($user))); } $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); diff --git a/Resources/config/cache.php b/Resources/config/cache.php index eceb9bdfd..ad4dca42d 100644 --- a/Resources/config/cache.php +++ b/Resources/config/cache.php @@ -83,7 +83,7 @@ '', // namespace 0, // default lifetime abstract_arg('version'), - sprintf('%s/pools/system', param('kernel.cache_dir')), + \sprintf('%s/pools/system', param('kernel.cache_dir')), service('logger')->ignoreOnInvalid(), ]) ->tag('cache.pool', ['clearer' => 'cache.system_clearer', 'reset' => 'reset']) @@ -105,7 +105,7 @@ ->args([ '', // namespace 0, // default lifetime - sprintf('%s/pools/app', param('kernel.cache_dir')), + \sprintf('%s/pools/app', param('kernel.cache_dir')), service('cache.default_marshaller')->ignoreOnInvalid(), ]) ->call('setLogger', [service('logger')->ignoreOnInvalid()]) diff --git a/Resources/config/collectors.php b/Resources/config/collectors.php index aa6d4e33c..954ddeffa 100644 --- a/Resources/config/collectors.php +++ b/Resources/config/collectors.php @@ -56,7 +56,7 @@ ->set('data_collector.logger', LoggerDataCollector::class) ->args([ service('logger')->ignoreOnInvalid(), - sprintf('%s/%s', param('kernel.build_dir'), param('kernel.container_class')), + \sprintf('%s/%s', param('kernel.build_dir'), param('kernel.container_class')), service('.virtual_request_stack')->ignoreOnInvalid(), ]) ->tag('monolog.logger', ['channel' => 'profiler']) diff --git a/Resources/config/services.php b/Resources/config/services.php index c85ccf5d0..895d2ce34 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -129,7 +129,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] ->args([ tagged_iterator('kernel.cache_warmer'), param('kernel.debug'), - sprintf('%s/%sDeprecations.log', param('kernel.build_dir'), param('kernel.container_class')), + \sprintf('%s/%sDeprecations.log', param('kernel.build_dir'), param('kernel.container_class')), ]) ->tag('container.no_preload') diff --git a/Routing/Router.php b/Routing/Router.php index 4dfb71e74..ede88740b 100644 --- a/Routing/Router.php +++ b/Routing/Router.php @@ -55,7 +55,7 @@ public function __construct(ContainerInterface $container, mixed $resource, arra } elseif ($container instanceof SymfonyContainerInterface) { $this->paramFetcher = $container->getParameter(...); } else { - throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); + throw new \LogicException(\sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); } $this->defaultLocale = $defaultLocale; @@ -168,7 +168,7 @@ private function resolve(mixed $value): mixed } if (preg_match('/^env\((?:\w++:)*+\w++\)$/', $match[1])) { - throw new RuntimeException(sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1])); + throw new RuntimeException(\sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1])); } $resolved = ($this->paramFetcher)($match[1]); @@ -185,7 +185,7 @@ private function resolve(mixed $value): mixed } } - throw new RuntimeException(sprintf('The container parameter "%s", used in the route configuration value "%s", must be a string or numeric, but it is of type "%s".', $match[1], $value, get_debug_type($resolved))); + throw new RuntimeException(\sprintf('The container parameter "%s", used in the route configuration value "%s", must be a string or numeric, but it is of type "%s".', $match[1], $value, get_debug_type($resolved))); }, $value); return str_replace('%%', '%', $escapedValue); diff --git a/Secrets/AbstractVault.php b/Secrets/AbstractVault.php index 374964a06..882ec7862 100644 --- a/Secrets/AbstractVault.php +++ b/Secrets/AbstractVault.php @@ -36,7 +36,7 @@ abstract public function list(bool $reveal = false): array; protected function validateName(string $name): void { if (!preg_match('/^\w++$/D', $name)) { - throw new \LogicException(sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name)); + throw new \LogicException(\sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name)); } } diff --git a/Secrets/DotenvVault.php b/Secrets/DotenvVault.php index 7bdd74c37..15952611a 100644 --- a/Secrets/DotenvVault.php +++ b/Secrets/DotenvVault.php @@ -44,7 +44,7 @@ public function seal(string $name, string $value): void file_put_contents($this->dotenvFile, $content); - $this->lastMessage = sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile)); + $this->lastMessage = \sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile)); } public function reveal(string $name): ?string @@ -54,7 +54,7 @@ public function reveal(string $name): ?string $v = $_ENV[$name] ?? (str_starts_with($name, 'HTTP_') ? null : ($_SERVER[$name] ?? null)); if ('' === ($v ?? '')) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); + $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); return null; } @@ -72,12 +72,12 @@ public function remove(string $name): bool if ($count) { file_put_contents($this->dotenvFile, $content); - $this->lastMessage = sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile)); + $this->lastMessage = \sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile)); return true; } - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); + $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); return false; } diff --git a/Secrets/SodiumVault.php b/Secrets/SodiumVault.php index f09c3b3af..74713e28c 100644 --- a/Secrets/SodiumVault.php +++ b/Secrets/SodiumVault.php @@ -61,7 +61,7 @@ public function generateKeys(bool $override = false): bool } if (!$override && null !== $this->encryptionKey) { - $this->lastMessage = sprintf('Sodium keys already exist at "%s*.{public,private}" and won\'t be overridden.', $this->getPrettyPath($this->pathPrefix)); + $this->lastMessage = \sprintf('Sodium keys already exist at "%s*.{public,private}" and won\'t be overridden.', $this->getPrettyPath($this->pathPrefix)); return false; } @@ -72,7 +72,7 @@ public function generateKeys(bool $override = false): bool $this->export('encrypt.public', $this->encryptionKey); $this->export('decrypt.private', $this->decryptionKey); - $this->lastMessage = sprintf('Sodium keys have been generated at "%s*.public/private.php".', $this->getPrettyPath($this->pathPrefix)); + $this->lastMessage = \sprintf('Sodium keys have been generated at "%s*.public/private.php".', $this->getPrettyPath($this->pathPrefix)); return true; } @@ -88,9 +88,9 @@ public function seal(string $name, string $value): void $list = $this->list(); $list[$name] = null; uksort($list, 'strnatcmp'); - file_put_contents($this->pathPrefix.'list.php', sprintf("pathPrefix.'list.php', \sprintf("lastMessage = sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + $this->lastMessage = \sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); } public function reveal(string $name): ?string @@ -100,13 +100,13 @@ public function reveal(string $name): ?string $filename = $this->getFilename($name); if (!is_file($file = $this->pathPrefix.$filename.'.php')) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); return null; } if (!\function_exists('sodium_crypto_box_seal')) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the "sodium" PHP extension missing. Try running "composer require paragonie/sodium_compat" if you cannot enable the extension."', $name); + $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as the "sodium" PHP extension missing. Try running "composer require paragonie/sodium_compat" if you cannot enable the extension."', $name); return null; } @@ -114,13 +114,13 @@ public function reveal(string $name): ?string $this->loadKeys(); if ('' === $this->decryptionKey) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); return null; } if (false === $value = sodium_crypto_box_seal_open(include $file, $this->decryptionKey)) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the wrong decryption key was provided for "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as the wrong decryption key was provided for "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); return null; } @@ -135,16 +135,16 @@ public function remove(string $name): bool $filename = $this->getFilename($name); if (!is_file($file = $this->pathPrefix.$filename.'.php')) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + $this->lastMessage = \sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); return false; } $list = $this->list(); unset($list[$name]); - file_put_contents($this->pathPrefix.'list.php', sprintf("pathPrefix.'list.php', \sprintf("lastMessage = sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + $this->lastMessage = \sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); return @unlink($file) || !file_exists($file); } @@ -206,7 +206,7 @@ private function loadKeys(): void } elseif ('' !== $this->decryptionKey) { $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); } else { - throw new \RuntimeException(sprintf('Encryption key not found in "%s".', \dirname($this->pathPrefix))); + throw new \RuntimeException(\sprintf('Encryption key not found in "%s".', \dirname($this->pathPrefix))); } } @@ -215,7 +215,7 @@ private function export(string $filename, string $data): void $b64 = 'decrypt.private' === $filename ? '// SYMFONY_DECRYPTION_SECRET='.base64_encode($data)."\n" : ''; $name = basename($this->pathPrefix.$filename); $data = str_replace('%', '\x', rawurlencode($data)); - $data = sprintf("createSecretsDir(); @@ -228,7 +228,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)) { - throw new \RuntimeException(sprintf('Unable to create the secrets directory (%s).', $this->secretsDir)); + throw new \RuntimeException(\sprintf('Unable to create the secrets directory (%s).', $this->secretsDir)); } $this->secretsDir = null; diff --git a/Test/BrowserKitAssertionsTrait.php b/Test/BrowserKitAssertionsTrait.php index 7eea648cb..1b7437b77 100644 --- a/Test/BrowserKitAssertionsTrait.php +++ b/Test/BrowserKitAssertionsTrait.php @@ -171,7 +171,7 @@ protected static function getClient(?AbstractBrowser $newClient = null): ?Abstra } if (!$client instanceof AbstractBrowser) { - static::fail(sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__)); + static::fail(\sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__)); } return $client; diff --git a/Test/DomCrawlerAssertionsTrait.php b/Test/DomCrawlerAssertionsTrait.php index 024c78f75..ede359bcc 100644 --- a/Test/DomCrawlerAssertionsTrait.php +++ b/Test/DomCrawlerAssertionsTrait.php @@ -126,18 +126,18 @@ public static function assertCheckboxNotChecked(string $fieldName, string $messa public static function assertFormValue(string $formSelector, string $fieldName, string $value, string $message = ''): void { $node = self::getCrawler()->filter($formSelector); - self::assertNotEmpty($node, sprintf('Form "%s" not found.', $formSelector)); + self::assertNotEmpty($node, \sprintf('Form "%s" not found.', $formSelector)); $values = $node->form()->getValues(); - self::assertArrayHasKey($fieldName, $values, $message ?: sprintf('Field "%s" not found in form "%s".', $fieldName, $formSelector)); + self::assertArrayHasKey($fieldName, $values, $message ?: \sprintf('Field "%s" not found in form "%s".', $fieldName, $formSelector)); self::assertSame($value, $values[$fieldName]); } public static function assertNoFormValue(string $formSelector, string $fieldName, string $message = ''): void { $node = self::getCrawler()->filter($formSelector); - self::assertNotEmpty($node, sprintf('Form "%s" not found.', $formSelector)); + self::assertNotEmpty($node, \sprintf('Form "%s" not found.', $formSelector)); $values = $node->form()->getValues(); - self::assertArrayNotHasKey($fieldName, $values, $message ?: sprintf('Field "%s" has a value in form "%s".', $fieldName, $formSelector)); + self::assertArrayNotHasKey($fieldName, $values, $message ?: \sprintf('Field "%s" has a value in form "%s".', $fieldName, $formSelector)); } private static function getCrawler(): Crawler diff --git a/Test/HttpClientAssertionsTrait.php b/Test/HttpClientAssertionsTrait.php index 20c64608e..9d22a822f 100644 --- a/Test/HttpClientAssertionsTrait.php +++ b/Test/HttpClientAssertionsTrait.php @@ -34,7 +34,7 @@ public static function assertHttpClientRequest(string $expectedUrl, string $expe $expectedRequestHasBeenFound = false; if (!\array_key_exists($httpClientId, $httpClientDataCollector->getClients())) { - static::fail(sprintf('HttpClient "%s" is not registered.', $httpClientId)); + static::fail(\sprintf('HttpClient "%s" is not registered.', $httpClientId)); } foreach ($httpClientDataCollector->getClients()[$httpClientId]['traces'] as $trace) { @@ -102,7 +102,7 @@ public function assertNotHttpClientRequest(string $unexpectedUrl, string $expect $unexpectedUrlHasBeenFound = false; if (!\array_key_exists($httpClientId, $httpClientDataCollector->getClients())) { - static::fail(sprintf('HttpClient "%s" is not registered.', $httpClientId)); + static::fail(\sprintf('HttpClient "%s" is not registered.', $httpClientId)); } foreach ($httpClientDataCollector->getClients()[$httpClientId]['traces'] as $trace) { @@ -114,7 +114,7 @@ public function assertNotHttpClientRequest(string $unexpectedUrl, string $expect } } - self::assertFalse($unexpectedUrlHasBeenFound, sprintf('Unexpected URL called: "%s" - "%s"', $expectedMethod, $unexpectedUrl)); + self::assertFalse($unexpectedUrlHasBeenFound, \sprintf('Unexpected URL called: "%s" - "%s"', $expectedMethod, $unexpectedUrl)); } public static function assertHttpClientRequestCount(int $count, string $httpClientId = 'http_client'): void diff --git a/Test/KernelTestCase.php b/Test/KernelTestCase.php index 632b782ad..9fd13323b 100644 --- a/Test/KernelTestCase.php +++ b/Test/KernelTestCase.php @@ -46,11 +46,11 @@ protected function tearDown(): void protected static function getKernelClass(): string { if (!isset($_SERVER['KERNEL_CLASS']) && !isset($_ENV['KERNEL_CLASS'])) { - throw new \LogicException(sprintf('You must set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel in phpunit.xml / phpunit.xml.dist or override the "%1$s::createKernel()" or "%1$s::getKernelClass()" method.', static::class)); + throw new \LogicException(\sprintf('You must set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel in phpunit.xml / phpunit.xml.dist or override the "%1$s::createKernel()" or "%1$s::getKernelClass()" method.', static::class)); } if (!class_exists($class = $_ENV['KERNEL_CLASS'] ?? $_SERVER['KERNEL_CLASS'])) { - throw new \RuntimeException(sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the "%s::createKernel()" method.', $class, static::class)); + throw new \RuntimeException(\sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the "%s::createKernel()" method.', $class, static::class)); } return $class; diff --git a/Test/TestContainer.php b/Test/TestContainer.php index e1e7a8592..77135fa06 100644 --- a/Test/TestContainer.php +++ b/Test/TestContainer.php @@ -78,7 +78,7 @@ public function set(string $id, mixed $service): void throw $e; } if (isset($container->privates[$renamedId])) { - throw new InvalidArgumentException(sprintf('The "%s" service is already initialized, you cannot replace it.', $id)); + throw new InvalidArgumentException(\sprintf('The "%s" service is already initialized, you cannot replace it.', $id)); } $container->privates[$renamedId] = $service; } diff --git a/Test/WebTestCase.php b/Test/WebTestCase.php index de31d4ba9..9c6ee9c98 100644 --- a/Test/WebTestCase.php +++ b/Test/WebTestCase.php @@ -38,7 +38,7 @@ protected function tearDown(): void protected static function createClient(array $options = [], array $server = []): KernelBrowser { if (static::$booted) { - throw new \LogicException(sprintf('Booting the kernel before calling "%s()" is not supported, the kernel should only be booted once.', __METHOD__)); + throw new \LogicException(\sprintf('Booting the kernel before calling "%s()" is not supported, the kernel should only be booted once.', __METHOD__)); } $kernel = static::bootKernel($options); diff --git a/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index b950b5fd9..753c39cc8 100644 --- a/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -62,7 +62,7 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() $configCacheFactory->cache( substr($file, 0, -5), function () use ($file) { - $this->fail(sprintf('Meta file "%s" is not fresh', (string) $file)); + $this->fail(\sprintf('Meta file "%s" is not fresh', (string) $file)); } ); } @@ -92,7 +92,7 @@ function () use ($file) { $containerRef->getFileName() ); $this->assertMatchesRegularExpression( - sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', $containerClass), + \sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', $containerClass), $this->fs->readFile($containerFile), 'kernel.container_class is properly set on the dumped container' ); diff --git a/Tests/Console/Descriptor/AbstractDescriptorTestCase.php b/Tests/Console/Descriptor/AbstractDescriptorTestCase.php index cc6b08fd2..dde1f000b 100644 --- a/Tests/Console/Descriptor/AbstractDescriptorTestCase.php +++ b/Tests/Console/Descriptor/AbstractDescriptorTestCase.php @@ -292,7 +292,7 @@ private static function getDescriptionTestData(iterable $objects): array { $data = []; foreach ($objects as $name => $object) { - $file = sprintf('%s.%s', trim($name, '.'), static::getFormat()); + $file = \sprintf('%s.%s', trim($name, '.'), static::getFormat()); $description = file_get_contents(__DIR__.'/../../Fixtures/Descriptor/'.$file); $data[] = [$object, $description, $file]; } @@ -313,7 +313,7 @@ private static function getContainerBuilderDescriptionTestData(array $objects): $data = []; foreach ($objects as $name => $object) { foreach ($variations as $suffix => $options) { - $file = sprintf('%s_%s.%s', trim($name, '.'), $suffix, static::getFormat()); + $file = \sprintf('%s_%s.%s', trim($name, '.'), $suffix, static::getFormat()); $description = file_get_contents(__DIR__.'/../../Fixtures/Descriptor/'.$file); $data[] = [$object, $description, $options, $file]; } @@ -332,7 +332,7 @@ private static function getEventDispatcherDescriptionTestData(array $objects): a $data = []; foreach ($objects as $name => $object) { foreach ($variations as $suffix => $options) { - $file = sprintf('%s_%s.%s', trim($name, '.'), $suffix, static::getFormat()); + $file = \sprintf('%s_%s.%s', trim($name, '.'), $suffix, static::getFormat()); $description = file_get_contents(__DIR__.'/../../Fixtures/Descriptor/'.$file); $data[] = [$object, $description, $options, $file]; } @@ -353,7 +353,7 @@ public static function getDescribeContainerBuilderWithPriorityTagsTestData(): ar $data = []; foreach (ObjectsProvider::getContainerBuildersWithPriorityTags() as $name => $object) { foreach ($variations as $suffix => $options) { - $file = sprintf('%s_%s.%s', trim($name, '.'), $suffix, static::getFormat()); + $file = \sprintf('%s_%s.%s', trim($name, '.'), $suffix, static::getFormat()); $description = file_get_contents(__DIR__.'/../../Fixtures/Descriptor/'.$file); $data[] = [$object, $description, $options]; } diff --git a/Tests/Console/Descriptor/TextDescriptorTest.php b/Tests/Console/Descriptor/TextDescriptorTest.php index 2404706d0..34e16f5e4 100644 --- a/Tests/Console/Descriptor/TextDescriptorTest.php +++ b/Tests/Console/Descriptor/TextDescriptorTest.php @@ -35,7 +35,7 @@ public static function getDescribeRouteWithControllerLinkTestData() foreach ($getDescribeData as $key => &$data) { $routeStub = $data[0]; - $routeStub->setDefault('_controller', sprintf('%s::%s', MyController::class, '__invoke')); + $routeStub->setDefault('_controller', \sprintf('%s::%s', MyController::class, '__invoke')); $file = $data[2]; $file = preg_replace('#(\..*?)$#', '_link$1', $file); $data = file_get_contents(__DIR__.'/../../Fixtures/Descriptor/'.$file); diff --git a/Tests/Controller/TestAbstractController.php b/Tests/Controller/TestAbstractController.php index 18f3eabb7..7c13aedb5 100644 --- a/Tests/Controller/TestAbstractController.php +++ b/Tests/Controller/TestAbstractController.php @@ -41,11 +41,11 @@ public function setContainer(ContainerInterface $container): ?ContainerInterface continue; } if (!isset($expected[$id])) { - throw new \UnexpectedValueException(sprintf('Service "%s" is not expected, as declared by "%s::getSubscribedServices()".', $id, AbstractController::class)); + throw new \UnexpectedValueException(\sprintf('Service "%s" is not expected, as declared by "%s::getSubscribedServices()".', $id, AbstractController::class)); } $type = substr($expected[$id], 1); if (!$container->get($id) instanceof $type) { - throw new \UnexpectedValueException(sprintf('Service "%s" is expected to be an instance of "%s", as declared by "%s::getSubscribedServices()".', $id, $type, AbstractController::class)); + throw new \UnexpectedValueException(\sprintf('Service "%s" is expected to be an instance of "%s", as declared by "%s::getSubscribedServices()".', $id, $type, AbstractController::class)); } } diff --git a/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php index d9785f1dc..b6021fbdd 100644 --- a/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php +++ b/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php @@ -29,7 +29,7 @@ public function testProcess() $pass->process($container); - $this->assertSame([sprintf('%s: Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?', UnusedTagsPass::class)], $container->getCompiler()->getLog()); + $this->assertSame([\sprintf('%s: Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?', UnusedTagsPass::class)], $container->getCompiler()->getLog()); } public function testMissingKnownTags() diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index cb97f2a47..cc88fb154 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1766,24 +1766,24 @@ public function testRedisTagAwareAdapter() 'cacheRedisTagAwareBaz2', ]; foreach ($argNames as $argumentName) { - $aliasesForArguments[] = sprintf('%s $%s', TagAwareCacheInterface::class, $argumentName); - $aliasesForArguments[] = sprintf('%s $%s', CacheInterface::class, $argumentName); - $aliasesForArguments[] = sprintf('%s $%s', CacheItemPoolInterface::class, $argumentName); + $aliasesForArguments[] = \sprintf('%s $%s', TagAwareCacheInterface::class, $argumentName); + $aliasesForArguments[] = \sprintf('%s $%s', CacheInterface::class, $argumentName); + $aliasesForArguments[] = \sprintf('%s $%s', CacheItemPoolInterface::class, $argumentName); } foreach ($aliasesForArguments as $aliasForArgumentStr) { $aliasForArgument = $container->getAlias($aliasForArgumentStr); - $this->assertNotNull($aliasForArgument, sprintf("No alias found for '%s'", $aliasForArgumentStr)); + $this->assertNotNull($aliasForArgument, \sprintf("No alias found for '%s'", $aliasForArgumentStr)); $def = $container->getDefinition((string) $aliasForArgument); - $this->assertInstanceOf(ChildDefinition::class, $def, sprintf("No definition found for '%s'", $aliasForArgumentStr)); + $this->assertInstanceOf(ChildDefinition::class, $def, \sprintf("No definition found for '%s'", $aliasForArgumentStr)); $defParent = $container->getDefinition($def->getParent()); if ($defParent instanceof ChildDefinition) { $defParent = $container->getDefinition($defParent->getParent()); } - $this->assertSame(RedisTagAwareAdapter::class, $defParent->getClass(), sprintf("'%s' is not %s", $aliasForArgumentStr, RedisTagAwareAdapter::class)); + $this->assertSame(RedisTagAwareAdapter::class, $defParent->getClass(), \sprintf("'%s' is not %s", $aliasForArgumentStr, RedisTagAwareAdapter::class)); } } @@ -2191,7 +2191,7 @@ public function testIfNotifierTransportsAreKnownByFrameworkExtension() foreach ((new Finder())->in(\dirname(__DIR__, 4).'/Component/Notifier/Bridge')->directories()->depth(0)->exclude('Mercure') as $bridgeDirectory) { $transportFactoryName = strtolower(preg_replace('/(.)([A-Z])/', '$1-$2', $bridgeDirectory->getFilename())); - $this->assertTrue($container->hasDefinition('notifier.transport_factory.'.$transportFactoryName), sprintf('Did you forget to add the "%s" TransportFactory to the $classToServices array in FrameworkExtension?', $bridgeDirectory->getFilename())); + $this->assertTrue($container->hasDefinition('notifier.transport_factory.'.$transportFactoryName), \sprintf('Did you forget to add the "%s" TransportFactory to the $classToServices array in FrameworkExtension?', $bridgeDirectory->getFilename())); } } @@ -2464,14 +2464,14 @@ private function assertVersionStrategy(ContainerBuilder $container, Reference $r private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $container, $id, $adapter, $defaultLifetime) { - $this->assertTrue($container->has($id), sprintf('Service definition "%s" for cache pool of type "%s" is registered', $id, $adapter)); + $this->assertTrue($container->has($id), \sprintf('Service definition "%s" for cache pool of type "%s" is registered', $id, $adapter)); $poolDefinition = $container->getDefinition($id); - $this->assertInstanceOf(ChildDefinition::class, $poolDefinition, sprintf('Cache pool "%s" is based on an abstract cache pool.', $id)); + $this->assertInstanceOf(ChildDefinition::class, $poolDefinition, \sprintf('Cache pool "%s" is based on an abstract cache pool.', $id)); - $this->assertTrue($poolDefinition->hasTag('cache.pool'), sprintf('Service definition "%s" is tagged with the "cache.pool" tag.', $id)); - $this->assertFalse($poolDefinition->isAbstract(), sprintf('Service definition "%s" is not abstract.', $id)); + $this->assertTrue($poolDefinition->hasTag('cache.pool'), \sprintf('Service definition "%s" is tagged with the "cache.pool" tag.', $id)); + $this->assertFalse($poolDefinition->isAbstract(), \sprintf('Service definition "%s" is not abstract.', $id)); $tag = $poolDefinition->getTag('cache.pool'); $this->assertArrayHasKey('default_lifetime', $tag[0], 'The default lifetime is stored as an attribute of the "cache.pool" tag.'); diff --git a/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php b/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php index b0d303128..989684bee 100644 --- a/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php +++ b/Tests/Functional/Bundle/TestBundle/Controller/SessionController.php @@ -35,13 +35,13 @@ public function welcomeAction(Request $request, $name = null) // remember name $session->set('name', $name); - return new Response(sprintf('Hello %s, nice to meet you.', $name)); + return new Response(\sprintf('Hello %s, nice to meet you.', $name)); } // existing session $name = $session->get('name'); - return new Response(sprintf('Welcome back %s, nice to meet you.', $name)); + return new Response(\sprintf('Welcome back %s, nice to meet you.', $name)); } public function cacheableAction() diff --git a/Tests/Functional/CacheAttributeListenerTest.php b/Tests/Functional/CacheAttributeListenerTest.php index 72b2c1226..e6eb93eba 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', '/', server: ['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', '/', server: ['HTTP_IF_NONE_MATCH' => \sprintf('"%s"', hash('sha256', '12345'))]); $response = $client->getResponse(); diff --git a/Tests/Functional/ConfigDebugCommandTest.php b/Tests/Functional/ConfigDebugCommandTest.php index c9bfba234..bd1539636 100644 --- a/Tests/Functional/ConfigDebugCommandTest.php +++ b/Tests/Functional/ConfigDebugCommandTest.php @@ -155,7 +155,7 @@ public function testDefaultParameterValueIsResolvedIfConfigIsExisting(bool $debu $this->assertSame(0, $ret, 'Returns 0 in case of success'); $kernelCacheDir = self::$kernel->getContainer()->getParameter('kernel.cache_dir'); - $this->assertStringContainsString(sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay()); + $this->assertStringContainsString(\sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay()); } /** diff --git a/Tests/Functional/ContainerDebugCommandTest.php b/Tests/Functional/ContainerDebugCommandTest.php index efbc1f54a..bb80a4484 100644 --- a/Tests/Functional/ContainerDebugCommandTest.php +++ b/Tests/Functional/ContainerDebugCommandTest.php @@ -205,7 +205,7 @@ public function testDescribeEnvVar() public function testGetDeprecation() { static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); - $path = sprintf('%s/%sDeprecations.log', static::$kernel->getContainer()->getParameter('kernel.build_dir'), static::$kernel->getContainer()->getParameter('kernel.container_class')); + $path = \sprintf('%s/%sDeprecations.log', static::$kernel->getContainer()->getParameter('kernel.build_dir'), static::$kernel->getContainer()->getParameter('kernel.container_class')); touch($path); file_put_contents($path, serialize([[ 'type' => 16384, @@ -235,7 +235,7 @@ public function testGetDeprecation() public function testGetDeprecationNone() { static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); - $path = sprintf('%s/%sDeprecations.log', static::$kernel->getContainer()->getParameter('kernel.build_dir'), static::$kernel->getContainer()->getParameter('kernel.container_class')); + $path = \sprintf('%s/%sDeprecations.log', static::$kernel->getContainer()->getParameter('kernel.build_dir'), static::$kernel->getContainer()->getParameter('kernel.container_class')); touch($path); file_put_contents($path, serialize([])); @@ -254,7 +254,7 @@ public function testGetDeprecationNone() public function testGetDeprecationNoFile() { static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); - $path = sprintf('%s/%sDeprecations.log', static::$kernel->getContainer()->getParameter('kernel.build_dir'), static::$kernel->getContainer()->getParameter('kernel.container_class')); + $path = \sprintf('%s/%sDeprecations.log', static::$kernel->getContainer()->getParameter('kernel.build_dir'), static::$kernel->getContainer()->getParameter('kernel.container_class')); @unlink($path); $application = new Application(static::$kernel); diff --git a/Tests/Functional/app/AppKernel.php b/Tests/Functional/app/AppKernel.php index 06dc2d637..d4d9c99bc 100644 --- a/Tests/Functional/app/AppKernel.php +++ b/Tests/Functional/app/AppKernel.php @@ -35,14 +35,14 @@ class AppKernel extends Kernel implements ExtensionInterface, ConfigurationInter public function __construct($varDir, $testCase, $rootConfig, $environment, $debug) { if (!is_dir(__DIR__.'/'.$testCase)) { - throw new \InvalidArgumentException(sprintf('The test case "%s" does not exist.', $testCase)); + throw new \InvalidArgumentException(\sprintf('The test case "%s" does not exist.', $testCase)); } $this->varDir = $varDir; $this->testCase = $testCase; $fs = new Filesystem(); if (!$fs->isAbsolutePath($rootConfig) && !file_exists($rootConfig = __DIR__.'/'.$testCase.'/'.$rootConfig)) { - throw new \InvalidArgumentException(sprintf('The root config "%s" does not exist.', $rootConfig)); + throw new \InvalidArgumentException(\sprintf('The root config "%s" does not exist.', $rootConfig)); } $this->rootConfig = $rootConfig; @@ -52,7 +52,7 @@ public function __construct($varDir, $testCase, $rootConfig, $environment, $debu public function registerBundles(): iterable { if (!file_exists($filename = $this->getProjectDir().'/'.$this->testCase.'/bundles.php')) { - throw new \RuntimeException(sprintf('The bundles file "%s" does not exist.', $filename)); + throw new \RuntimeException(\sprintf('The bundles file "%s" does not exist.', $filename)); } return include $filename; diff --git a/Translation/Translator.php b/Translation/Translator.php index 870d69ae1..84aa0c7fd 100644 --- a/Translation/Translator.php +++ b/Translation/Translator.php @@ -81,7 +81,7 @@ public function __construct( ) { // check option names if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff))); + throw new InvalidArgumentException(\sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff))); } $this->options = array_merge($this->options, $options); From 4736b77df25094bfcf7e116c92a91c05c61a3de2 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 16 Jun 2024 17:17:26 +0200 Subject: [PATCH 090/180] chore: CS fixes --- Tests/DependencyInjection/ConfigurationTest.php | 14 +++++++------- .../Routing/RedirectableCompiledUrlMatcherTest.php | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index b32d8681b..6f2a51993 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -224,13 +224,13 @@ public function testInvalidAssetsConfiguration(array $assetConfig, $expectedMess $this->expectExceptionMessage($expectedMessage); $processor->processConfiguration($configuration, [ - [ - 'http_method_override' => false, - 'handle_all_throwables' => true, - 'php_errors' => ['log' => true], - 'assets' => $assetConfig, - ], - ]); + [ + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'assets' => $assetConfig, + ], + ]); } public static function provideInvalidAssetConfigurationTests(): iterable diff --git a/Tests/Routing/RedirectableCompiledUrlMatcherTest.php b/Tests/Routing/RedirectableCompiledUrlMatcherTest.php index 29126e130..9a96313d0 100644 --- a/Tests/Routing/RedirectableCompiledUrlMatcherTest.php +++ b/Tests/Routing/RedirectableCompiledUrlMatcherTest.php @@ -27,7 +27,8 @@ public function testRedirectWhenNoSlash() $matcher = $this->getMatcher($routes, $context = new RequestContext()); - $this->assertEquals([ + $this->assertEquals( + [ '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', 'path' => '/foo/', 'permanent' => true, @@ -47,7 +48,8 @@ public function testSchemeRedirect() $matcher = $this->getMatcher($routes, $context = new RequestContext()); - $this->assertEquals([ + $this->assertEquals( + [ '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', 'path' => '/foo', 'permanent' => true, From 900b8add71b63351d9d87907e3b3b7ffcabb5adc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 25 Jun 2024 08:08:32 +0200 Subject: [PATCH 091/180] Unify how --format is handle by commands --- Command/ConfigDebugCommand.php | 7 ++----- Command/ConfigDumpReferenceCommand.php | 9 +++------ Command/ContainerDebugCommand.php | 4 ++++ Command/EventDispatcherDebugCommand.php | 5 +++++ Command/RouterDebugCommand.php | 4 ++++ 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Command/ConfigDebugCommand.php b/Command/ConfigDebugCommand.php index fb79b39bf..55c101e9c 100644 --- a/Command/ConfigDebugCommand.php +++ b/Command/ConfigDebugCommand.php @@ -41,9 +41,6 @@ class ConfigDebugCommand extends AbstractConfigCommand { protected function configure(): void { - $commentedHelpFormats = array_map(fn ($format) => \sprintf('%s', $format), $this->getAvailableFormatOptions()); - $helpFormats = implode('", "', $commentedHelpFormats); - $this ->setDefinition([ new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), @@ -60,8 +57,7 @@ protected function configure(): void 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 command output: php %command.full_name% framework --format=json @@ -268,6 +264,7 @@ private static function buildPathsCompletion(array $paths, string $prefix = ''): return $completionPaths; } + /** @return string[] */ private function getAvailableFormatOptions(): array { return ['txt', 'yaml', 'json']; diff --git a/Command/ConfigDumpReferenceCommand.php b/Command/ConfigDumpReferenceCommand.php index 27dc01b11..7e5cd765f 100644 --- a/Command/ConfigDumpReferenceCommand.php +++ b/Command/ConfigDumpReferenceCommand.php @@ -39,9 +39,6 @@ class ConfigDumpReferenceCommand extends AbstractConfigCommand { protected function configure(): void { - $commentedHelpFormats = array_map(fn ($format) => \sprintf('%s', $format), $this->getAvailableFormatOptions()); - $helpFormats = implode('", "', $commentedHelpFormats); - $this ->setDefinition([ new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), @@ -57,10 +54,9 @@ protected function configure(): void 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 command output: - php %command.full_name% FrameworkBundle --format=xml + php %command.full_name% FrameworkBundle --format=json For dumping a specific option, add its path as second argument (only available for the yaml format): @@ -181,6 +177,7 @@ private function getAvailableBundles(): array return $bundles; } + /** @return string[] */ private function getAvailableFormatOptions(): array { return ['yaml', 'xml']; diff --git a/Command/ContainerDebugCommand.php b/Command/ContainerDebugCommand.php index 9619d1972..46cdca9ab 100644 --- a/Command/ContainerDebugCommand.php +++ b/Command/ContainerDebugCommand.php @@ -106,6 +106,9 @@ protected function configure(): void php %command.full_name% --show-hidden +The --format option specifies the format of the command output: + + php %command.full_name% --format=json EOF ) ; @@ -358,6 +361,7 @@ public function filterToServiceTypes(string $serviceId): bool return class_exists($serviceId) || interface_exists($serviceId, false); } + /** @return string[] */ private function getAvailableFormatOptions(): array { return (new DescriptorHelper())->getFormats(); diff --git a/Command/EventDispatcherDebugCommand.php b/Command/EventDispatcherDebugCommand.php index a3531d800..3c51cb1b7 100644 --- a/Command/EventDispatcherDebugCommand.php +++ b/Command/EventDispatcherDebugCommand.php @@ -60,6 +60,10 @@ protected function configure(): void To get specific listeners for an event, specify its name: php %command.full_name% kernel.request + +The --format option specifies the format of the command output: + + php %command.full_name% --format=json EOF ) ; @@ -153,6 +157,7 @@ private function searchForEvent(EventDispatcherInterface $dispatcher, string $ne return $output; } + /** @return string[] */ private function getAvailableFormatOptions(): array { return (new DescriptorHelper())->getFormats(); diff --git a/Command/RouterDebugCommand.php b/Command/RouterDebugCommand.php index d57c0623f..13a6f75d0 100644 --- a/Command/RouterDebugCommand.php +++ b/Command/RouterDebugCommand.php @@ -61,6 +61,9 @@ protected function configure(): void php %command.full_name% +The --format option specifies the format of the command output: + + php %command.full_name% --format=json EOF ) ; @@ -164,6 +167,7 @@ private function findRouteContaining(string $name, RouteCollection $routes): Rou return $foundRoutes; } + /** @return string[] */ private function getAvailableFormatOptions(): array { return (new DescriptorHelper())->getFormats(); From ab5d785db2e90f3508eb58957aebe756c8bef410 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 20 Jun 2024 08:01:34 -0400 Subject: [PATCH 092/180] Lazy kernel.secret parameter resolving --- Resources/config/services.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/config/services.php b/Resources/config/services.php index 895d2ce34..4095af666 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -23,6 +23,7 @@ use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\DependencyInjection\Config\ContainerParametersResourceChecker; use Symfony\Component\DependencyInjection\EnvVarProcessor; +use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag; use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; @@ -154,7 +155,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] ->set('uri_signer', UriSigner::class) ->args([ - param('kernel.secret'), + new Parameter('kernel.secret') ]) ->alias(UriSigner::class, 'uri_signer') From 35d085dc18b494d20b75728ecb222543e760c515 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 27 Jun 2024 14:04:56 +0200 Subject: [PATCH 093/180] [FrameworkBundle] Fix warming up routes --- Routing/Router.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Routing/Router.php b/Routing/Router.php index 4dfb71e74..69428a1b7 100644 --- a/Routing/Router.php +++ b/Routing/Router.php @@ -69,7 +69,7 @@ public function getRouteCollection(): RouteCollection $this->collection->addResource(new ContainerParametersResource($this->collectedParameters)); try { - $containerFile = ($this->paramFetcher)('kernel.cache_dir').'/'.($this->paramFetcher)('kernel.container_class').'.php'; + $containerFile = ($this->paramFetcher)('kernel.build_dir').'/'.($this->paramFetcher)('kernel.container_class').'.php'; if (file_exists($containerFile)) { $this->collection->addResource(new FileResource($containerFile)); } else { @@ -84,14 +84,12 @@ public function getRouteCollection(): RouteCollection public function warmUp(string $cacheDir, ?string $buildDir = null): array { - if (!$buildDir) { - return []; + if (null === $currentDir = $this->getOption('cache_dir')) { + return []; // skip warmUp when router doesn't use cache } - $currentDir = $this->getOption('cache_dir'); - - // force cache generation in build_dir - $this->setOption('cache_dir', $buildDir); + // force cache generation + $this->setOption('cache_dir', $buildDir ?? $cacheDir); $this->getMatcher(); $this->getGenerator(); From 8e79d91740601e27db4d9ab78d40bd697c20379f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Mon, 1 Jul 2024 02:16:34 +0200 Subject: [PATCH 094/180] Remove useless uniqid in tempnam calls --- Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php | 3 ++- Tests/Command/TranslationDebugCommandTest.php | 6 ++++-- .../TranslationUpdateCommandCompletionTest.php | 3 ++- Tests/Command/TranslationUpdateCommandTest.php | 13 ++----------- Tests/Functional/BundlePathsTest.php | 3 ++- Tests/Routing/RouterTest.php | 4 +++- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php b/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php index 294a3cd25..cf5f88c15 100644 --- a/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php +++ b/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php @@ -37,8 +37,9 @@ class ConfigBuilderCacheWarmerTest extends TestCase protected function setUp(): void { - $this->varDir = sys_get_temp_dir().'/'.uniqid(); $fs = new Filesystem(); + $this->varDir = tempnam(sys_get_temp_dir(), 'sf_var_'); + $fs->remove($this->varDir); $fs->mkdir($this->varDir); } diff --git a/Tests/Command/TranslationDebugCommandTest.php b/Tests/Command/TranslationDebugCommandTest.php index dcff845a3..c6c91a857 100644 --- a/Tests/Command/TranslationDebugCommandTest.php +++ b/Tests/Command/TranslationDebugCommandTest.php @@ -82,7 +82,8 @@ public function testDebugDefaultRootDirectory() { $this->fs->remove($this->translationDir); $this->fs = new Filesystem(); - $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf_translation', true); + $this->translationDir = tempnam(sys_get_temp_dir(), 'sf_translation_'); + $this->fs->remove($this->translationDir); $this->fs->mkdir($this->translationDir.'/translations'); $this->fs->mkdir($this->translationDir.'/templates'); @@ -150,7 +151,8 @@ public function testNoErrorWithOnlyUnusedOptionAndNoResults() protected function setUp(): void { $this->fs = new Filesystem(); - $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf_translation', true); + $this->translationDir = tempnam(sys_get_temp_dir(), 'sf_translation_'); + $this->fs->remove($this->translationDir); $this->fs->mkdir($this->translationDir.'/translations'); $this->fs->mkdir($this->translationDir.'/templates'); } diff --git a/Tests/Command/TranslationUpdateCommandCompletionTest.php b/Tests/Command/TranslationUpdateCommandCompletionTest.php index 1b11a6111..4627508cb 100644 --- a/Tests/Command/TranslationUpdateCommandCompletionTest.php +++ b/Tests/Command/TranslationUpdateCommandCompletionTest.php @@ -57,7 +57,8 @@ public static function provideCompletionSuggestions(): iterable protected function setUp(): void { $this->fs = new Filesystem(); - $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf_translation', true); + $this->translationDir = tempnam(sys_get_temp_dir(), 'sf_translation_'); + $this->fs->remove($this->translationDir); $this->fs->mkdir($this->translationDir.'/translations'); $this->fs->mkdir($this->translationDir.'/templates'); } diff --git a/Tests/Command/TranslationUpdateCommandTest.php b/Tests/Command/TranslationUpdateCommandTest.php index d9f142e8f..def589f58 100644 --- a/Tests/Command/TranslationUpdateCommandTest.php +++ b/Tests/Command/TranslationUpdateCommandTest.php @@ -78,11 +78,6 @@ public function testDumpWrongSortAndClean() public function testDumpMessagesAndCleanInRootDirectory() { - $this->fs->remove($this->translationDir); - $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf_translation', true); - $this->fs->mkdir($this->translationDir.'/translations'); - $this->fs->mkdir($this->translationDir.'/templates'); - $tester = $this->createCommandTester(['messages' => ['foo' => 'foo']], [], null, [$this->translationDir.'/trans'], [$this->translationDir.'/views']); $tester->execute(['command' => 'translation:extract', 'locale' => 'en', '--dump-messages' => true, '--clean' => true]); $this->assertMatchesRegularExpression('/foo/', $tester->getDisplay()); @@ -115,11 +110,6 @@ public function testWriteMessages() public function testWriteMessagesInRootDirectory() { - $this->fs->remove($this->translationDir); - $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf_translation', true); - $this->fs->mkdir($this->translationDir.'/translations'); - $this->fs->mkdir($this->translationDir.'/templates'); - $tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]); $tester->execute(['command' => 'translation:extract', 'locale' => 'en', '--force' => true]); $this->assertMatchesRegularExpression('/Translation files were successfully updated./', $tester->getDisplay()); @@ -174,7 +164,8 @@ public function testFilterDuplicateTransPaths() protected function setUp(): void { $this->fs = new Filesystem(); - $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf_translation', true); + $this->translationDir = tempnam(sys_get_temp_dir(), 'sf_translation_'); + $this->fs->remove($this->translationDir); $this->fs->mkdir($this->translationDir.'/translations'); $this->fs->mkdir($this->translationDir.'/templates'); } diff --git a/Tests/Functional/BundlePathsTest.php b/Tests/Functional/BundlePathsTest.php index a079837c9..a06803434 100644 --- a/Tests/Functional/BundlePathsTest.php +++ b/Tests/Functional/BundlePathsTest.php @@ -23,9 +23,10 @@ class BundlePathsTest extends AbstractWebTestCase public function testBundlePublicDir() { $kernel = static::bootKernel(['test_case' => 'BundlePaths']); - $projectDir = sys_get_temp_dir().'/'.uniqid('sf_bundle_paths', true); + $projectDir = tempnam(sys_get_temp_dir(), 'sf_bundle_paths_'); $fs = new Filesystem(); + $fs->remove($projectDir); $fs->mkdir($projectDir.'/public'); $command = (new Application($kernel))->add(new AssetsInstallCommand($fs, $projectDir)); $exitCode = (new CommandTester($command))->execute(['target' => $projectDir.'/public']); diff --git a/Tests/Routing/RouterTest.php b/Tests/Routing/RouterTest.php index 11c0dc7e6..d2c021563 100644 --- a/Tests/Routing/RouterTest.php +++ b/Tests/Routing/RouterTest.php @@ -530,7 +530,9 @@ public static function getNonStringValues() */ public function testCacheValidityWithContainerParameters($parameter) { - $cacheDir = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('router_', true); + $cacheDir = tempnam(sys_get_temp_dir(), 'sf_router_'); + unlink($cacheDir); + mkdir($cacheDir); try { $container = new Container(); From 213321d07b71574142ec950dacf84867f131d458 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Mon, 1 Jul 2024 16:00:19 +0200 Subject: [PATCH 095/180] [TypeInfo] Add PhpDocAwareReflectionTypeResolver --- DependencyInjection/FrameworkExtension.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 7cc67725e..04d45f59f 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -14,6 +14,7 @@ use Composer\InstalledVersions; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; +use Symfony\Component\TypeInfo\TypeResolver\PhpDocAwareReflectionTypeResolver; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Types\ContextFactory; use PhpParser\Parser; @@ -1974,11 +1975,21 @@ private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpF if (ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/type-info'])) { $container->register('type_info.resolver.string', StringTypeResolver::class); + $container->register('type_info.resolver.reflection_parameter.phpdoc_aware', PhpDocAwareReflectionTypeResolver::class) + ->setArguments([new Reference('type_info.resolver.reflection_parameter'), new Reference('type_info.resolver.string'), new Reference('type_info.type_context_factory')]); + $container->register('type_info.resolver.reflection_property.phpdoc_aware', PhpDocAwareReflectionTypeResolver::class) + ->setArguments([new Reference('type_info.resolver.reflection_property'), new Reference('type_info.resolver.string'), new Reference('type_info.type_context_factory')]); + $container->register('type_info.resolver.reflection_return.phpdoc_aware', PhpDocAwareReflectionTypeResolver::class) + ->setArguments([new Reference('type_info.resolver.reflection_return'), new Reference('type_info.resolver.string'), new Reference('type_info.type_context_factory')]); + /** @var ServiceLocatorArgument $resolversLocator */ $resolversLocator = $container->getDefinition('type_info.resolver')->getArgument(0); - $resolversLocator->setValues($resolversLocator->getValues() + [ + $resolversLocator->setValues([ 'string' => new Reference('type_info.resolver.string'), - ]); + \ReflectionParameter::class => new Reference('type_info.resolver.reflection_parameter.phpdoc_aware'), + \ReflectionProperty::class => new Reference('type_info.resolver.reflection_property.phpdoc_aware'), + \ReflectionFunctionAbstract::class => new Reference('type_info.resolver.reflection_return.phpdoc_aware'), + ] + $resolversLocator->getValues()); } } From eeac11247208e54653d91a5f426038fe71e0e612 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 5 Jul 2024 08:25:30 +0200 Subject: [PATCH 096/180] [Notifier] Remove the Gitter bridge --- DependencyInjection/FrameworkExtension.php | 1 - Resources/config/notifier_transports.php | 1 - 2 files changed, 2 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 7cc67725e..7e5f88fde 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2779,7 +2779,6 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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\Gitter\GitterTransportFactory::class => 'notifier.transport_factory.gitter', 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 4acfcf783..e34781e9c 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -31,7 +31,6 @@ 'discord' => Bridge\Discord\DiscordTransportFactory::class, 'fake-chat' => Bridge\FakeChat\FakeChatTransportFactory::class, 'firebase' => Bridge\Firebase\FirebaseTransportFactory::class, - 'gitter' => Bridge\Gitter\GitterTransportFactory::class, 'google-chat' => Bridge\GoogleChat\GoogleChatTransportFactory::class, 'line-notify' => Bridge\LineNotify\LineNotifyTransportFactory::class, 'linked-in' => Bridge\LinkedIn\LinkedInTransportFactory::class, From e81f2c33de7786829621d7d10a5fa24dee8d5dbe Mon Sep 17 00:00:00 2001 From: Piotr Zajac Date: Tue, 28 May 2024 13:26:56 +0200 Subject: [PATCH 097/180] validate empty request MapQueryString/MapRequestPayload skips validation when empty request is sent resolves #54617 --- Tests/Functional/ApiAttributesTest.php | 846 ++++++++++++++++-- .../app/ApiAttributesTest/routing.yml | 28 +- 2 files changed, 799 insertions(+), 75 deletions(-) diff --git a/Tests/Functional/ApiAttributesTest.php b/Tests/Functional/ApiAttributesTest.php index 96b6d0ee9..a64da93b3 100644 --- a/Tests/Functional/ApiAttributesTest.php +++ b/Tests/Functional/ApiAttributesTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use Composer\InstalledVersions; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -23,13 +24,14 @@ class ApiAttributesTest extends AbstractWebTestCase /** * @dataProvider mapQueryStringProvider */ - public function testMapQueryString(array $query, string $expectedResponse, int $expectedStatusCode) + public function testMapQueryString(string $uri, array $query, string $expectedResponse, int $expectedStatusCode) { $client = self::createClient(['test_case' => 'ApiAttributesTest']); - $client->request('GET', '/map-query-string.json', $query); + $client->request('GET', $uri, $query); $response = $client->getResponse(); + if ($expectedResponse) { self::assertJsonStringEqualsJsonString($expectedResponse, $response->getContent()); } else { @@ -40,13 +42,70 @@ public function testMapQueryString(array $query, string $expectedResponse, int $ public static function mapQueryStringProvider(): iterable { - yield 'empty' => [ + yield 'empty query string mapping nullable attribute' => [ + 'uri' => '/map-query-string-to-nullable-attribute.json', 'query' => [], 'expectedResponse' => '', 'expectedStatusCode' => 204, ]; - yield 'valid' => [ + yield 'valid query string mapping nullable attribute' => [ + 'uri' => '/map-query-string-to-nullable-attribute.json', + 'query' => ['filter' => ['status' => 'approved', 'quantity' => '4']], + 'expectedResponse' => <<<'JSON' + { + "filter": { + "status": "approved", + "quantity": 4 + } + } + JSON, + 'expectedStatusCode' => 200, + ]; + + yield 'invalid query string mapping nullable attribute' => [ + 'uri' => '/map-query-string-to-nullable-attribute.json', + 'query' => ['filter' => ['status' => 'approved', 'quantity' => '200']], + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 404, + "detail": "filter.quantity: This value should be less than 10.", + "violations": [ + { + "propertyPath": "filter.quantity", + "title": "This value should be less than 10.", + "template": "This value should be less than {{ compared_value }}.", + "parameters": { + "{{ value }}": "200", + "{{ compared_value }}": "10", + "{{ compared_value_type }}": "int" + }, + "type": "urn:uuid:079d7420-2d13-460c-8756-de810eeb37d2" + } + ] + } + JSON, + 'expectedStatusCode' => 404, + ]; + + yield 'empty query string mapping attribute with default value' => [ + 'uri' => '/map-query-string-to-attribute-with-default-value.json', + 'query' => [], + 'expectedResponse' => <<<'JSON' + { + "filter": { + "status": "approved", + "quantity": 5 + } + } + JSON, + 'expectedStatusCode' => 200, + ]; + + yield 'valid query string mapping attribute with default value' => [ + 'uri' => '/map-query-string-to-attribute-with-default-value.json', 'query' => ['filter' => ['status' => 'approved', 'quantity' => '4']], 'expectedResponse' => <<<'JSON' { @@ -59,7 +118,8 @@ public static function mapQueryStringProvider(): iterable 'expectedStatusCode' => 200, ]; - yield 'invalid' => [ + yield 'invalid query string mapping attribute with default value' => [ + 'uri' => '/map-query-string-to-attribute-with-default-value.json', 'query' => ['filter' => ['status' => 'approved', 'quantity' => '200']], 'expectedResponse' => <<<'JSON' { @@ -84,12 +144,92 @@ public static function mapQueryStringProvider(): iterable JSON, 'expectedStatusCode' => 404, ]; + + $expectedResponse = <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 404, + "detail": "filter: This value should be of type Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter.", + "violations": [ + { + "parameters": { + "hint": "Failed to create object because the class misses the \"filter\" property.", + "{{ type }}": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter" + }, + "propertyPath": "filter", + "template": "This value should be of type {{ type }}.", + "title": "This value should be of type Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter." + } + ] + } + JSON; + + $httpKernelVersion = InstalledVersions::getVersion('symfony/http-kernel'); + if ($httpKernelVersion && version_compare($httpKernelVersion, '7.2.0', '<')) { + $expectedResponse = <<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 404, + "detail": "Not Found" + } + JSON; + } + + yield 'empty query string mapping non-nullable attribute without default value' => [ + 'uri' => '/map-query-string-to-non-nullable-attribute-without-default-value.json', + 'query' => [], + 'expectedResponse' => $expectedResponse, + 'expectedStatusCode' => 404, + ]; + + yield 'valid query string mapping non-nullable attribute without default value' => [ + 'uri' => '/map-query-string-to-non-nullable-attribute-without-default-value.json', + 'query' => ['filter' => ['status' => 'approved', 'quantity' => '4']], + 'expectedResponse' => <<<'JSON' + { + "filter": { + "status": "approved", + "quantity": 4 + } + } + JSON, + 'expectedStatusCode' => 200, + ]; + + yield 'invalid query string mapping non-nullable attribute without default value' => [ + 'uri' => '/map-query-string-to-non-nullable-attribute-without-default-value.json', + 'query' => ['filter' => ['status' => 'approved', 'quantity' => '11']], + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 404, + "detail": "filter.quantity: This value should be less than 10.", + "violations": [ + { + "propertyPath": "filter.quantity", + "title": "This value should be less than 10.", + "template": "This value should be less than {{ compared_value }}.", + "parameters": { + "{{ value }}": "11", + "{{ compared_value }}": "10", + "{{ compared_value_type }}": "int" + }, + "type": "urn:uuid:079d7420-2d13-460c-8756-de810eeb37d2" + } + ] + } + JSON, + 'expectedStatusCode' => 404, + ]; } /** * @dataProvider mapRequestPayloadProvider */ - public function testMapRequestPayload(string $format, array $parameters, ?string $content, string $expectedResponse, int $expectedStatusCode) + public function testMapRequestPayload(string $uri, string $format, array $parameters, ?string $content, string $expectedResponse, int $expectedStatusCode) { $client = self::createClient(['test_case' => 'ApiAttributesTest']); @@ -102,7 +242,7 @@ public function testMapRequestPayload(string $format, array $parameters, ?string $client->request( 'POST', - '/map-request-body.'.$format, + $uri, $parameters, [], ['HTTP_ACCEPT' => $acceptHeader, 'CONTENT_TYPE' => $acceptHeader], @@ -123,7 +263,8 @@ public function testMapRequestPayload(string $format, array $parameters, ?string public static function mapRequestPayloadProvider(): iterable { - yield 'empty' => [ + yield 'empty request mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', 'format' => 'json', 'parameters' => [], 'content' => '', @@ -131,7 +272,8 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 204, ]; - yield 'valid json' => [ + yield 'valid request with json content mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', 'format' => 'json', 'parameters' => [], 'content' => <<<'JSON' @@ -149,7 +291,41 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 200, ]; - yield 'malformed json' => [ + yield 'valid request with xml content mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.xml', + 'format' => 'xml', + 'parameters' => [], + 'content' => <<<'XML' + + Hello everyone! + true + + XML, + 'expectedResponse' => <<<'XML' + + Hello everyone! + 1 + + XML, + 'expectedStatusCode' => 200, + ]; + + yield 'valid request mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', + 'format' => 'json', + 'parameters' => ['comment' => 'Hello everyone!', 'approved' => '0'], + 'content' => null, + 'expectedResponse' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedStatusCode' => 200, + ]; + + yield 'malformed json request mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', 'format' => 'json', 'parameters' => [], 'content' => <<<'JSON' @@ -169,7 +345,8 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 400, ]; - yield 'unsupported format' => [ + yield 'request with unsupported format mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.dummy', 'format' => 'dummy', 'parameters' => [], 'content' => 'Hello', @@ -177,25 +354,8 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 415, ]; - yield 'valid xml' => [ - 'format' => 'xml', - 'parameters' => [], - 'content' => <<<'XML' - - Hello everyone! - true - - XML, - 'expectedResponse' => <<<'XML' - - Hello everyone! - 1 - - XML, - 'expectedStatusCode' => 200, - ]; - - yield 'invalid type' => [ + yield 'request with invalid type mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', 'format' => 'json', 'parameters' => [], 'content' => <<<'JSON' @@ -225,7 +385,8 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 422, ]; - yield 'validation error json' => [ + yield 'invalid request with json content mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', 'format' => 'json', 'parameters' => [], 'content' => <<<'JSON' @@ -267,7 +428,8 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 422, ]; - yield 'validation error xml' => [ + yield 'invalid request with xml content mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.xml', 'format' => 'xml', 'parameters' => [], 'content' => <<<'XML' @@ -299,22 +461,10 @@ public static function mapRequestPayloadProvider(): iterable 'expectedStatusCode' => 422, ]; - yield 'valid input' => [ - 'format' => 'json', - 'input' => ['comment' => 'Hello everyone!', 'approved' => '0'], - 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, - 'expectedStatusCode' => 200, - ]; - - yield 'validation error input' => [ + yield 'invalid request mapping nullable attribute' => [ + 'uri' => '/map-request-to-nullable-attribute.json', 'format' => 'json', - 'input' => ['comment' => '', 'approved' => '1'], + 'parameters' => ['comment' => '', 'approved' => '1'], 'content' => null, 'expectedResponse' => <<<'JSON' { @@ -348,32 +498,590 @@ public static function mapRequestPayloadProvider(): iterable JSON, 'expectedStatusCode' => 422, ]; - } -} -class WithMapQueryStringController -{ - public function __invoke(#[MapQueryString] ?QueryString $query): Response - { - if (!$query) { - return new Response('', Response::HTTP_NO_CONTENT); - } + yield 'empty request mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => '', + 'expectedResponse' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedStatusCode' => 200, + ]; - return new JsonResponse( - ['filter' => ['status' => $query->filter->status, 'quantity' => $query->filter->quantity]], - ); - } -} + yield 'valid request with json content mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedStatusCode' => 200, + ]; -class WithMapRequestPayloadController -{ - public function __invoke(#[MapRequestPayload] ?RequestBody $body, Request $request): Response - { - if ('json' === $request->getPreferredFormat('json')) { - if (!$body) { - return new Response('', Response::HTTP_NO_CONTENT); - } + yield 'valid request with xml content mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.xml', + 'format' => 'xml', + 'parameters' => [], + 'content' => <<<'XML' + + Hello everyone! + true + + XML, + 'expectedResponse' => <<<'XML' + + Hello everyone! + 1 + + XML, + 'expectedStatusCode' => 200, + ]; + + yield 'valid request mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'parameters' => ['comment' => 'Hello everyone!', 'approved' => '0'], + 'content' => null, + 'expectedResponse' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedStatusCode' => 200, + ]; + yield 'malformed json request mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false, + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 400, + "detail": "Bad Request" + } + JSON, + 'expectedStatusCode' => 400, + ]; + + yield 'request with unsupported format mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.dummy', + 'format' => 'dummy', + 'parameters' => [], + 'content' => 'Hello', + 'expectedResponse' => '415 Unsupported Media Type', + 'expectedStatusCode' => 415, + ]; + + yield 'request with invalid type mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": "string instead of bool" + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "approved: This value should be of type bool.", + "violations": [ + { + "propertyPath": "approved", + "title": "This value should be of type bool.", + "template": "This value should be of type {{ type }}.", + "parameters": { + "{{ type }}": "bool" + } + } + ] + } + JSON, + 'expectedStatusCode' => 422, + ]; + + yield 'invalid request with json content mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "", + "approved": true + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", + "violations": [ + { + "propertyPath": "comment", + "title": "This value should not be blank.", + "template": "This value should not be blank.", + "parameters": { + "{{ value }}": "\"\"" + }, + "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" + }, + { + "propertyPath": "comment", + "title": "This value is too short. It should have 10 characters or more.", + "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", + "parameters": { + "{{ value }}": "\"\"", + "{{ limit }}": "10", + "{{ value_length }}": "0" + }, + "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" + } + ] + } + JSON, + 'expectedStatusCode' => 422, + ]; + + yield 'invalid request with xml content mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.xml', + 'format' => 'xml', + 'parameters' => [], + 'content' => <<<'XML' + + H + false + + XML, + 'expectedResponse' => <<<'XML' + + + https://symfony.com/errors/validation + Validation Failed + 422 + comment: This value is too short. It should have 10 characters or more. + + comment + This value is too short. It should have 10 characters or more. + + + "H" + 10 + 1 + + urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 + + + XML, + 'expectedStatusCode' => 422, + ]; + + yield 'invalid request mapping attribute with default value' => [ + 'uri' => '/map-request-to-attribute-with-default-value.json', + 'format' => 'json', + 'input' => ['comment' => '', 'approved' => '1'], + 'content' => null, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", + "violations": [ + { + "propertyPath": "comment", + "title": "This value should not be blank.", + "template": "This value should not be blank.", + "parameters": { + "{{ value }}": "\"\"" + }, + "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" + }, + { + "propertyPath": "comment", + "title": "This value is too short. It should have 10 characters or more.", + "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", + "parameters": { + "{{ value }}": "\"\"", + "{{ limit }}": "10", + "{{ value_length }}": "0" + }, + "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" + } + ] + } + JSON, + 'expectedStatusCode' => 422, + ]; + + $expectedStatusCode = 400; + $expectedResponse = <<<'JSON' + { + "type":"https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title":"An error occurred", + "status":400, + "detail":"Bad Request" + } + JSON; + + $httpKernelVersion = InstalledVersions::getVersion('symfony/http-kernel'); + if ($httpKernelVersion && version_compare($httpKernelVersion, '7.2.0', '<')) { + $expectedStatusCode = 422; + $expectedResponse = <<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 422, + "detail": "Unprocessable Content" + } + JSON; + } + + yield 'empty request mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => '', + 'expectedResponse' => $expectedResponse, + 'expectedStatusCode' => $expectedStatusCode, + ]; + + yield 'valid request with json content mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedStatusCode' => 200, + ]; + + yield 'valid request with xml content mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.xml', + 'format' => 'xml', + 'parameters' => [], + 'content' => <<<'XML' + + Hello everyone! + true + + XML, + 'expectedResponse' => <<<'XML' + + Hello everyone! + 1 + + XML, + 'expectedStatusCode' => 200, + ]; + + yield 'valid request mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'parameters' => ['comment' => 'Hello everyone!', 'approved' => '0'], + 'content' => null, + 'expectedResponse' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + 'expectedStatusCode' => 200, + ]; + + yield 'malformed json request mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": false, + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 400, + "detail": "Bad Request" + } + JSON, + 'expectedStatusCode' => 400, + ]; + + yield 'request with unsupported format mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.dummy', + 'format' => 'dummy', + 'parameters' => [], + 'content' => 'Hello', + 'expectedResponse' => '415 Unsupported Media Type', + 'expectedStatusCode' => 415, + ]; + + yield 'request with invalid type mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "Hello everyone!", + "approved": "string instead of bool" + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "approved: This value should be of type bool.", + "violations": [ + { + "propertyPath": "approved", + "title": "This value should be of type bool.", + "template": "This value should be of type {{ type }}.", + "parameters": { + "{{ type }}": "bool" + } + } + ] + } + JSON, + 'expectedStatusCode' => 422, + ]; + + yield 'invalid request with json content mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'parameters' => [], + 'content' => <<<'JSON' + { + "comment": "", + "approved": true + } + JSON, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", + "violations": [ + { + "propertyPath": "comment", + "title": "This value should not be blank.", + "template": "This value should not be blank.", + "parameters": { + "{{ value }}": "\"\"" + }, + "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" + }, + { + "propertyPath": "comment", + "title": "This value is too short. It should have 10 characters or more.", + "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", + "parameters": { + "{{ value }}": "\"\"", + "{{ limit }}": "10", + "{{ value_length }}": "0" + }, + "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" + } + ] + } + JSON, + 'expectedStatusCode' => 422, + ]; + + yield 'invalid request with xml content mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.xml', + 'format' => 'xml', + 'parameters' => [], + 'content' => <<<'XML' + + H + false + + XML, + 'expectedResponse' => <<<'XML' + + + https://symfony.com/errors/validation + Validation Failed + 422 + comment: This value is too short. It should have 10 characters or more. + + comment + This value is too short. It should have 10 characters or more. + + + "H" + 10 + 1 + + urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 + + + XML, + 'expectedStatusCode' => 422, + ]; + + yield 'invalid request mapping non-nullable attribute without default value' => [ + 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', + 'format' => 'json', + 'input' => ['comment' => '', 'approved' => '1'], + 'content' => null, + 'expectedResponse' => <<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", + "violations": [ + { + "propertyPath": "comment", + "title": "This value should not be blank.", + "template": "This value should not be blank.", + "parameters": { + "{{ value }}": "\"\"" + }, + "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" + }, + { + "propertyPath": "comment", + "title": "This value is too short. It should have 10 characters or more.", + "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", + "parameters": { + "{{ value }}": "\"\"", + "{{ limit }}": "10", + "{{ value_length }}": "0" + }, + "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" + } + ] + } + JSON, + 'expectedStatusCode' => 422, + ]; + } +} + +class WithMapQueryStringToNullableAttributeController +{ + public function __invoke(#[MapQueryString] ?QueryString $query): Response + { + if (!$query) { + return new Response('', Response::HTTP_NO_CONTENT); + } + + return new JsonResponse( + ['filter' => ['status' => $query->filter->status, 'quantity' => $query->filter->quantity]], + ); + } +} + +class WithMapQueryStringToAttributeWithDefaultValueController +{ + public function __invoke(#[MapQueryString] QueryString $query = new QueryString(new Filter('approved', 5))): Response + { + return new JsonResponse( + ['filter' => ['status' => $query->filter->status, 'quantity' => $query->filter->quantity]], + ); + } +} + +class WithMapQueryStringToNonNullableAttributeWithoutDefaultValueController +{ + public function __invoke(#[MapQueryString] QueryString $query): Response + { + return new JsonResponse( + ['filter' => ['status' => $query->filter->status, 'quantity' => $query->filter->quantity]], + ); + } +} + +class WithMapRequestToNullableAttributeController +{ + public function __invoke(#[MapRequestPayload] ?RequestBody $body, Request $request): Response + { + if ('json' === $request->getPreferredFormat('json')) { + if (!$body) { + return new Response('', Response::HTTP_NO_CONTENT); + } + + return new JsonResponse(['comment' => $body->comment, 'approved' => $body->approved]); + } + + return new Response( + << + {$body->comment} + {$body->approved} + + XML + ); + } +} + +class WithMapRequestToAttributeWithDefaultValueController +{ + public function __invoke(Request $request, #[MapRequestPayload] RequestBody $body = new RequestBody('Hello everyone!', false)): Response + { + if ('json' === $request->getPreferredFormat('json')) { + return new JsonResponse(['comment' => $body->comment, 'approved' => $body->approved]); + } + + return new Response( + << + {$body->comment} + {$body->approved} + + XML + ); + } +} + +class WithMapRequestToNonNullableAttributeWithoutDefaultValueController +{ + public function __invoke(Request $request, #[MapRequestPayload] RequestBody $body): Response + { + if ('json' === $request->getPreferredFormat('json')) { return new JsonResponse(['comment' => $body->comment, 'approved' => $body->approved]); } diff --git a/Tests/Functional/app/ApiAttributesTest/routing.yml b/Tests/Functional/app/ApiAttributesTest/routing.yml index 9ec40e170..a2827eb3d 100644 --- a/Tests/Functional/app/ApiAttributesTest/routing.yml +++ b/Tests/Functional/app/ApiAttributesTest/routing.yml @@ -1,7 +1,23 @@ -map_query_string: - path: /map-query-string.{_format} - controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapQueryStringController +map_query_string_to_nullable_attribute: + path: /map-query-string-to-nullable-attribute.{_format} + controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapQueryStringToNullableAttributeController -map_request_body: - path: /map-request-body.{_format} - controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapRequestPayloadController +map_query_string_to_attribute_with_default_value: + path: /map-query-string-to-attribute-with-default-value.{_format} + controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapQueryStringToAttributeWithDefaultValueController + +map_query_string_to_non_nullable_attribute_without_default_value: + path: /map-query-string-to-non-nullable-attribute-without-default-value.{_format} + controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapQueryStringToNonNullableAttributeWithoutDefaultValueController + +map_request_to_nullable_attribute: + path: /map-request-to-nullable-attribute.{_format} + controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapRequestToNullableAttributeController + +map_request_to_attribute_with_default_value: + path: /map-request-to-attribute-with-default-value.{_format} + controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapRequestToAttributeWithDefaultValueController + +map_request_to_non_nullable_attribute_without_default_value: + path: /map-request-to-non-nullable-attribute-without-default-value.{_format} + controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\WithMapRequestToNonNullableAttributeWithoutDefaultValueController From 5fae5196cdc2a00726300a831b0c274df44e89a9 Mon Sep 17 00:00:00 2001 From: Lukas Kaltenbach Date: Tue, 2 Jul 2024 20:45:16 +0200 Subject: [PATCH 098/180] [Notifier] Add Sipgate bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 1114246cc..46ba61aa6 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2801,6 +2801,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 5ddc9ae24..98ff2d50c 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -93,6 +93,7 @@ 'ring-central' => Bridge\RingCentral\RingCentralTransportFactory::class, 'sendberry' => Bridge\Sendberry\SendberryTransportFactory::class, 'sevenio' => Bridge\Sevenio\SevenIoTransportFactory::class, + 'sipgate' => Bridge\Sipgate\SipgateTransportFactory::class, 'simple-textin' => Bridge\SimpleTextin\SimpleTextinTransportFactory::class, 'sinch' => Bridge\Sinch\SinchTransportFactory::class, 'sms-biuras' => Bridge\SmsBiuras\SmsBiurasTransportFactory::class, From f497f34253377b8f85644a7380d6f9299649c66d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 6 Jul 2024 09:57:16 +0200 Subject: [PATCH 099/180] Update .gitattributes --- .gitattributes | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index 84c7add05..14c3c3594 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ /Tests export-ignore /phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore +/.git* export-ignore From a6929df8c5b9862552f16dbb9d37f815ef58307f Mon Sep 17 00:00:00 2001 From: Petrisor Ciprian Daniel Date: Sat, 6 Jul 2024 22:13:31 +0300 Subject: [PATCH 100/180] [FrameworkBundle] Add `exit` option to `secrets:decrypt-to-local` command --- CHANGELOG.md | 1 + Command/SecretsDecryptToLocalCommand.php | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2470d542..2db5b9674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * Derivate `kernel.secret` from the decryption secret when its env var is not defined * Make the `config/` directory optional in `MicroKernelTrait`, add support for service arguments in the invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing + * Add `exit` option for `secrets:decrypt-to-local` command 7.1 --- diff --git a/Command/SecretsDecryptToLocalCommand.php b/Command/SecretsDecryptToLocalCommand.php index b078769d8..e98a6d54d 100644 --- a/Command/SecretsDecryptToLocalCommand.php +++ b/Command/SecretsDecryptToLocalCommand.php @@ -38,15 +38,20 @@ public function __construct( protected function configure(): void { $this + ->addOption('exit', null, InputOption::VALUE_NONE, 'Returns a non-zero exit code if any errors are encountered') ->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. %command.full_name% -When the option --force is provided, secrets that already exist in the local vault are overriden. +When the --force option is provided, secrets that already exist in the local vault are overriden. %command.full_name% --force + +When the --exit option is provided, the command will return a non-zero exit code if any errors are encountered. + + %command.full_name% --exit EOF ) ; @@ -83,9 +88,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int ]); } + $hadErrors = false; foreach ($secrets as $k => $v) { if (null === $v) { $io->error($this->vault->getLastMessage() ?? \sprintf('Secret "%s" has been skipped as there was an error reading it.', $k)); + $hadErrors = true; continue; } @@ -93,6 +100,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->note($this->localVault->getLastMessage()); } + if ($hadErrors && $input->getOption('exit')) { + return 1; + } + return 0; } } From 4495b7fe12f3f5f013a98ceb9b0511ac6a015217 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Mon, 15 Jul 2024 14:43:16 +0200 Subject: [PATCH 101/180] Use `createMock` --- Tests/Controller/AbstractControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Controller/AbstractControllerTest.php b/Tests/Controller/AbstractControllerTest.php index 0dc06f30e..55a363984 100644 --- a/Tests/Controller/AbstractControllerTest.php +++ b/Tests/Controller/AbstractControllerTest.php @@ -431,7 +431,7 @@ public function testRenderViewWithForm() { $formView = new FormView(); - $form = $this->getMockBuilder(FormInterface::class)->getMock(); + $form = $this->createMock(FormInterface::class); $form->expects($this->once())->method('createView')->willReturn($formView); $twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(); @@ -452,7 +452,7 @@ public function testRenderWithFormSubmittedAndInvalid() { $formView = new FormView(); - $form = $this->getMockBuilder(FormInterface::class)->getMock(); + $form = $this->createMock(FormInterface::class); $form->expects($this->once())->method('createView')->willReturn($formView); $form->expects($this->once())->method('isSubmitted')->willReturn(true); $form->expects($this->once())->method('isValid')->willReturn(false); From 0931874388879f3c3b7219228755a9f53bd880a4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 17 Jul 2024 10:14:50 +0200 Subject: [PATCH 102/180] do not use uniqid() for generating dev tool tokens --- EventListener/ConsoleProfilerListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventListener/ConsoleProfilerListener.php b/EventListener/ConsoleProfilerListener.php index 3df9c61b9..4a8c9015e 100644 --- a/EventListener/ConsoleProfilerListener.php +++ b/EventListener/ConsoleProfilerListener.php @@ -77,7 +77,7 @@ public function initialize(ConsoleCommandEvent $event): void return; } - $request->attributes->set('_stopwatch_token', substr(hash('xxh128', uniqid(mt_rand(), true)), 0, 6)); + $request->attributes->set('_stopwatch_token', bin2hex(random_bytes(3))); $this->stopwatch->openSection(); } From 3a8d803cbea3badde4ac41a069adc93a883e4eb1 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 19 Jul 2024 10:48:20 +0200 Subject: [PATCH 103/180] [HttpFoundation][HttpKernel] Remove dead code and useless casts --- CacheWarmer/RouterCacheWarmer.php | 2 +- CacheWarmer/TranslationsCacheWarmer.php | 2 +- Tests/CacheWarmer/RouterCacheWarmerTest.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CacheWarmer/RouterCacheWarmer.php b/CacheWarmer/RouterCacheWarmer.php index 149d20ce3..052bfb39d 100644 --- a/CacheWarmer/RouterCacheWarmer.php +++ b/CacheWarmer/RouterCacheWarmer.php @@ -43,7 +43,7 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array $router = $this->container->get('router'); if ($router instanceof WarmableInterface) { - return (array) $router->warmUp($cacheDir, $buildDir); + return $router->warmUp($cacheDir, $buildDir); } throw new \LogicException(\sprintf('The router "%s" cannot be warmed up because it does not implement "%s".', get_debug_type($router), WarmableInterface::class)); diff --git a/CacheWarmer/TranslationsCacheWarmer.php b/CacheWarmer/TranslationsCacheWarmer.php index 19b2725c9..3b04a9bc2 100644 --- a/CacheWarmer/TranslationsCacheWarmer.php +++ b/CacheWarmer/TranslationsCacheWarmer.php @@ -40,7 +40,7 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array $this->translator ??= $this->container->get('translator'); if ($this->translator instanceof WarmableInterface) { - return (array) $this->translator->warmUp($cacheDir, $buildDir); + return $this->translator->warmUp($cacheDir, $buildDir); } return []; diff --git a/Tests/CacheWarmer/RouterCacheWarmerTest.php b/Tests/CacheWarmer/RouterCacheWarmerTest.php index 615010a47..06f738f2b 100644 --- a/Tests/CacheWarmer/RouterCacheWarmerTest.php +++ b/Tests/CacheWarmer/RouterCacheWarmerTest.php @@ -24,6 +24,8 @@ public function testWarmUpWithWarmableInterfaceWithBuildDir() $container = new Container(); $routerMock = $this->getMockBuilder(testRouterInterfaceWithWarmableInterface::class)->onlyMethods(['match', 'generate', 'getContext', 'setContext', 'getRouteCollection', 'warmUp'])->getMock(); + $routerMock->method('warmUp')->willReturn([]); + $container->set('router', $routerMock); $routerCacheWarmer = new RouterCacheWarmer($container); From 0643d07ef409d8246ffbab8a1f9205fda4998303 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 22 Jul 2024 12:05:17 +0200 Subject: [PATCH 104/180] terminate with non-zero exit code when a secret could not be read The fix for #42038 did a bit too much. Not only did it fix the PHP error that wasn't caught before, but also changed the exit code of the command. With this change the PHP error will still be prevented, but the command will terminate with a non-zero exit code to indicate the failure that occurred while reading the stored secrets. --- CHANGELOG.md | 2 +- Command/SecretsDecryptToLocalCommand.php | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2db5b9674..7058a3fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ CHANGELOG * Derivate `kernel.secret` from the decryption secret when its env var is not defined * Make the `config/` directory optional in `MicroKernelTrait`, add support for service arguments in the invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing - * Add `exit` option for `secrets:decrypt-to-local` command + * [BC BREAK] The `secrets:decrypt-to-local` command terminates with a non-zero exit code when a secret could not be read 7.1 --- diff --git a/Command/SecretsDecryptToLocalCommand.php b/Command/SecretsDecryptToLocalCommand.php index a88924646..c46da963b 100644 --- a/Command/SecretsDecryptToLocalCommand.php +++ b/Command/SecretsDecryptToLocalCommand.php @@ -38,7 +38,6 @@ public function __construct( protected function configure(): void { $this - ->addOption('exit', null, InputOption::VALUE_NONE, 'Returns a non-zero exit code if any errors are encountered') ->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. @@ -48,10 +47,6 @@ protected function configure(): void When the --force option is provided, secrets that already exist in the local vault are overridden. %command.full_name% --force - -When the --exit option is provided, the command will return a non-zero exit code if any errors are encountered. - - %command.full_name% --exit EOF ) ; @@ -100,7 +95,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->note($this->localVault->getLastMessage()); } - if ($hadErrors && $input->getOption('exit')) { + if ($hadErrors) { return 1; } From d99ca6e6321b4db25d74fbc99ef4fbc1e6f7adcc Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 22 Jul 2024 10:27:43 +0200 Subject: [PATCH 105/180] Use CPP where possible --- CacheWarmer/CachePoolClearerCacheWarmer.php | 11 ++++------- CacheWarmer/ConfigBuilderCacheWarmer.php | 11 ++++------- CacheWarmer/RouterCacheWarmer.php | 12 ++++++------ CacheWarmer/TranslationsCacheWarmer.php | 11 ++++++----- Routing/Router.php | 13 +++++++++---- Secrets/SodiumVault.php | 9 +++++---- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/CacheWarmer/CachePoolClearerCacheWarmer.php b/CacheWarmer/CachePoolClearerCacheWarmer.php index ae27502cf..e67f84dac 100644 --- a/CacheWarmer/CachePoolClearerCacheWarmer.php +++ b/CacheWarmer/CachePoolClearerCacheWarmer.php @@ -25,16 +25,13 @@ */ final class CachePoolClearerCacheWarmer implements CacheWarmerInterface { - private Psr6CacheClearer $poolClearer; - private array $pools; - /** * @param string[] $pools */ - public function __construct(Psr6CacheClearer $poolClearer, array $pools = []) - { - $this->poolClearer = $poolClearer; - $this->pools = $pools; + public function __construct( + private Psr6CacheClearer $poolClearer, + private array $pools = [], + ) { } public function warmUp(string $cacheDir, ?string $buildDir = null): array diff --git a/CacheWarmer/ConfigBuilderCacheWarmer.php b/CacheWarmer/ConfigBuilderCacheWarmer.php index 8b692c9c7..48ed51aec 100644 --- a/CacheWarmer/ConfigBuilderCacheWarmer.php +++ b/CacheWarmer/ConfigBuilderCacheWarmer.php @@ -34,13 +34,10 @@ */ class ConfigBuilderCacheWarmer implements CacheWarmerInterface { - private KernelInterface $kernel; - private ?LoggerInterface $logger; - - public function __construct(KernelInterface $kernel, ?LoggerInterface $logger = null) - { - $this->kernel = $kernel; - $this->logger = $logger; + public function __construct( + private KernelInterface $kernel, + private ?LoggerInterface $logger = null, + ) { } public function warmUp(string $cacheDir, ?string $buildDir = null): array diff --git a/CacheWarmer/RouterCacheWarmer.php b/CacheWarmer/RouterCacheWarmer.php index 149d20ce3..352d6e145 100644 --- a/CacheWarmer/RouterCacheWarmer.php +++ b/CacheWarmer/RouterCacheWarmer.php @@ -26,12 +26,12 @@ */ class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { - private ContainerInterface $container; - - public function __construct(ContainerInterface $container) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; + /** + * As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + */ + public function __construct( + private ContainerInterface $container, + ) { } public function warmUp(string $cacheDir, ?string $buildDir = null): array diff --git a/CacheWarmer/TranslationsCacheWarmer.php b/CacheWarmer/TranslationsCacheWarmer.php index 19b2725c9..ceed4e6ed 100644 --- a/CacheWarmer/TranslationsCacheWarmer.php +++ b/CacheWarmer/TranslationsCacheWarmer.php @@ -26,13 +26,14 @@ */ class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { - private ContainerInterface $container; private TranslatorInterface $translator; - public function __construct(ContainerInterface $container) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; + /** + * As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + */ + public function __construct( + private ContainerInterface $container, + ) { } public function warmUp(string $cacheDir, ?string $buildDir = null): array diff --git a/Routing/Router.php b/Routing/Router.php index 44d222a86..9efa07fae 100644 --- a/Routing/Router.php +++ b/Routing/Router.php @@ -35,16 +35,21 @@ */ class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface { - private ContainerInterface $container; private array $collectedParameters = []; private \Closure $paramFetcher; /** * @param mixed $resource The main resource to load */ - public function __construct(ContainerInterface $container, mixed $resource, array $options = [], ?RequestContext $context = null, ?ContainerInterface $parameters = null, ?LoggerInterface $logger = null, ?string $defaultLocale = null) - { - $this->container = $container; + public function __construct( + private ContainerInterface $container, + mixed $resource, + array $options = [], + ?RequestContext $context = null, + ?ContainerInterface $parameters = null, + ?LoggerInterface $logger = null, + ?string $defaultLocale = null, + ) { $this->resource = $resource; $this->context = $context ?? new RequestContext(); $this->logger = $logger; diff --git a/Secrets/SodiumVault.php b/Secrets/SodiumVault.php index 74713e28c..f747fed14 100644 --- a/Secrets/SodiumVault.php +++ b/Secrets/SodiumVault.php @@ -26,18 +26,19 @@ class SodiumVault extends AbstractVault implements EnvVarLoaderInterface private string|\Stringable|null $decryptionKey = null; private string $pathPrefix; private ?string $secretsDir; - private ?string $derivedSecretEnvVar; /** * @param $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault * or null to store generated keys in the provided $secretsDir */ - public function __construct(string $secretsDir, #[\SensitiveParameter] string|\Stringable|null $decryptionKey = null, ?string $derivedSecretEnvVar = null) - { + public function __construct( + string $secretsDir, + #[\SensitiveParameter] string|\Stringable|null $decryptionKey = null, + private ?string $derivedSecretEnvVar = null, + ) { $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.basename($secretsDir).'.'; $this->decryptionKey = $decryptionKey; $this->secretsDir = $secretsDir; - $this->derivedSecretEnvVar = $derivedSecretEnvVar; } public function generateKeys(bool $override = false): bool From 6ae2ba1a467890c38cd94146f63aa2e2d31103d0 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 19 Jul 2024 13:24:25 +0200 Subject: [PATCH 106/180] [Cache][Config][Console][DependencyInjection][FrameworkBundle] Remove dead code and useless casts --- CacheWarmer/AbstractPhpFileCacheWarmer.php | 2 +- Console/Descriptor/XmlDescriptor.php | 4 ++-- DependencyInjection/FrameworkExtension.php | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CacheWarmer/AbstractPhpFileCacheWarmer.php b/CacheWarmer/AbstractPhpFileCacheWarmer.php index d809888be..a18faae7d 100644 --- a/CacheWarmer/AbstractPhpFileCacheWarmer.php +++ b/CacheWarmer/AbstractPhpFileCacheWarmer.php @@ -58,7 +58,7 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array */ protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values): array { - return (array) $phpArrayAdapter->warmUp($values); + return $phpArrayAdapter->warmUp($values); } /** diff --git a/Console/Descriptor/XmlDescriptor.php b/Console/Descriptor/XmlDescriptor.php index dd2744f80..c41ac296f 100644 --- a/Console/Descriptor/XmlDescriptor.php +++ b/Console/Descriptor/XmlDescriptor.php @@ -64,7 +64,7 @@ protected function describeContainerService(object $service, array $options = [] protected function describeContainerServices(ContainerBuilder $container, array $options = []): void { - $this->writeDocument($this->getContainerServicesDocument($container, $options['tag'] ?? null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], $options['filter'] ?? null, $options['id'] ?? null)); + $this->writeDocument($this->getContainerServicesDocument($container, $options['tag'] ?? null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], $options['filter'] ?? null)); } protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void @@ -288,7 +288,7 @@ private function getContainerServiceDocument(object $service, string $id, ?Conta return $dom; } - private function getContainerServicesDocument(ContainerBuilder $container, ?string $tag = null, bool $showHidden = false, bool $showArguments = false, ?callable $filter = null, ?string $id = null): \DOMDocument + private function getContainerServicesDocument(ContainerBuilder $container, ?string $tag = null, bool $showHidden = false, bool $showArguments = false, ?callable $filter = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($containerXML = $dom->createElement('container')); diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index ac4c21114..49821a043 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -498,7 +498,7 @@ public function load(array $configs, ContainerBuilder $container): void if (!$messengerEnabled) { throw new LogicException('Scheduler support cannot be enabled as the Messenger component is not '.(interface_exists(MessageBusInterface::class) ? 'enabled.' : 'installed. Try running "composer require symfony/messenger".')); } - $this->registerSchedulerConfiguration($config['scheduler'], $container, $loader); + $this->registerSchedulerConfiguration($container, $loader); } else { $container->removeDefinition('cache.scheduler'); $container->removeDefinition('console.command.scheduler_debug'); @@ -570,7 +570,7 @@ public function load(array $configs, ContainerBuilder $container): void } if ($this->readConfigEnabled('remote-event', $container, $config['remote-event'])) { - $this->registerRemoteEventConfiguration($config['remote-event'], $container, $loader); + $this->registerRemoteEventConfiguration($loader); } if ($this->readConfigEnabled('html_sanitizer', $container, $config['html_sanitizer'])) { @@ -2073,7 +2073,7 @@ private function registerSemaphoreConfiguration(array $config, ContainerBuilder } } - private function registerSchedulerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void + private function registerSchedulerConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void { if (!class_exists(SchedulerTransportFactory::class)) { throw new LogicException('Scheduler support cannot be enabled as the Scheduler component is not installed. Try running "composer require symfony/scheduler".'); @@ -2940,7 +2940,7 @@ private function registerWebhookConfiguration(array $config, ContainerBuilder $c $controller->replaceArgument(1, new Reference($config['message_bus'])); } - private function registerRemoteEventConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void + private function registerRemoteEventConfiguration(PhpFileLoader $loader): void { if (!class_exists(RemoteEvent::class)) { throw new LogicException('RemoteEvent support cannot be enabled as the component is not installed. Try running "composer require symfony/remote-event".'); From 0c8ac7da2b89cdd69dbb7072ff41a102b5aa4dfa Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 31 Jul 2024 16:13:26 +0200 Subject: [PATCH 107/180] Remove unused code and unnecessary `else` branches --- Controller/ControllerResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/ControllerResolver.php b/Controller/ControllerResolver.php index 269709963..ef9ca3993 100644 --- a/Controller/ControllerResolver.php +++ b/Controller/ControllerResolver.php @@ -27,9 +27,9 @@ 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; From 5b2ddbbf95108ea92616ca611ed1c693d7161369 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 5 Aug 2024 09:12:25 +0200 Subject: [PATCH 108/180] Fix multiple CS errors --- Command/SecretsDecryptToLocalCommand.php | 2 +- DependencyInjection/FrameworkExtension.php | 2 +- Resources/config/services.php | 2 +- Tests/DependencyInjection/ConfigurationTest.php | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Command/SecretsDecryptToLocalCommand.php b/Command/SecretsDecryptToLocalCommand.php index c46da963b..4e392b677 100644 --- a/Command/SecretsDecryptToLocalCommand.php +++ b/Command/SecretsDecryptToLocalCommand.php @@ -95,7 +95,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->note($this->localVault->getLastMessage()); } - if ($hadErrors) { + if ($hadErrors) { return 1; } diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 49821a043..067e631c7 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -14,7 +14,6 @@ use Composer\InstalledVersions; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; -use Symfony\Component\TypeInfo\TypeResolver\PhpDocAwareReflectionTypeResolver; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Types\ContextFactory; use PhpParser\Parser; @@ -173,6 +172,7 @@ use Symfony\Component\Translation\PseudoLocalizationTranslator; use Symfony\Component\Translation\Translator; use Symfony\Component\TypeInfo\Type; +use Symfony\Component\TypeInfo\TypeResolver\PhpDocAwareReflectionTypeResolver; use Symfony\Component\TypeInfo\TypeResolver\StringTypeResolver; use Symfony\Component\Uid\Factory\UuidFactory; use Symfony\Component\Uid\UuidV4; diff --git a/Resources/config/services.php b/Resources/config/services.php index 4095af666..53856f356 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -155,7 +155,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] ->set('uri_signer', UriSigner::class) ->args([ - new Parameter('kernel.secret') + new Parameter('kernel.secret'), ]) ->alias(UriSigner::class, 'uri_signer') diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 793be0283..bad27f8ee 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -13,7 +13,6 @@ use Doctrine\DBAL\Connection; use PHPUnit\Framework\TestCase; -use Seld\JsonLint\JsonParser; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration; use Symfony\Bundle\FullStack; use Symfony\Component\Cache\Adapter\DoctrineAdapter; From 13dabdf3364ddaf3d4e439318144c32bbcfe11e9 Mon Sep 17 00:00:00 2001 From: Roy de Vos Burchart Date: Thu, 1 Aug 2024 17:21:17 +0200 Subject: [PATCH 109/180] Code style change in `@PER-CS2.0` affecting `@Symfony` (parentheses for anonymous classes) --- Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php | 10 +++++----- .../DependencyInjection/Compiler/ProfilerPassTest.php | 4 ++-- Tests/Test/WebTestCaseTest.php | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php b/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php index cf5f88c15..994151807 100644 --- a/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php +++ b/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php @@ -189,7 +189,7 @@ public function testExtensionAddedInKernel() $kernel = new class($this->varDir) extends TestKernel { protected function build(ContainerBuilder $container): void { - $container->registerExtension(new class() extends Extension implements ConfigurationInterface { + $container->registerExtension(new class extends Extension implements ConfigurationInterface { public function load(array $configs, ContainerBuilder $container): void { } @@ -276,7 +276,7 @@ protected function build(ContainerBuilder $container): void { /** @var TestSecurityExtension $extension */ $extension = $container->getExtension('test_security'); - $extension->addAuthenticatorFactory(new class() implements TestAuthenticatorFactoryInterface { + $extension->addAuthenticatorFactory(new class implements TestAuthenticatorFactoryInterface { public function getKey(): string { return 'token'; @@ -292,19 +292,19 @@ public function registerBundles(): iterable { yield from parent::registerBundles(); - yield new class() extends Bundle { + yield new class extends Bundle { public function getContainerExtension(): ExtensionInterface { return new TestSecurityExtension(); } }; - yield new class() extends Bundle { + yield new class extends Bundle { public function build(ContainerBuilder $container): void { /** @var TestSecurityExtension $extension */ $extension = $container->getExtension('test_security'); - $extension->addAuthenticatorFactory(new class() implements TestAuthenticatorFactoryInterface { + $extension->addAuthenticatorFactory(new class implements TestAuthenticatorFactoryInterface { public function getKey(): string { return 'form-login'; diff --git a/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/Tests/DependencyInjection/Compiler/ProfilerPassTest.php index 1b699d4d1..5a2215009 100644 --- a/Tests/DependencyInjection/Compiler/ProfilerPassTest.php +++ b/Tests/DependencyInjection/Compiler/ProfilerPassTest.php @@ -66,7 +66,7 @@ public function testValidCollector() public static function provideValidCollectorWithTemplateUsingAutoconfigure(): \Generator { - yield [new class() implements TemplateAwareDataCollectorInterface { + yield [new class implements TemplateAwareDataCollectorInterface { public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { } @@ -86,7 +86,7 @@ public static function getTemplate(): string } }]; - yield [new class() extends AbstractDataCollector { + yield [new class extends AbstractDataCollector { public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { } diff --git a/Tests/Test/WebTestCaseTest.php b/Tests/Test/WebTestCaseTest.php index 54a8044b0..effc7b081 100644 --- a/Tests/Test/WebTestCaseTest.php +++ b/Tests/Test/WebTestCaseTest.php @@ -388,7 +388,7 @@ private function getRequestTester(): WebTestCase private function getTester(KernelBrowser $client): WebTestCase { - $tester = new class() extends WebTestCase { + $tester = new class extends WebTestCase { use WebTestAssertionsTrait { getClient as public; } From 6b21a82872bf856946bdd8f9319f78d7a8b4b20a Mon Sep 17 00:00:00 2001 From: Jonas Claes Date: Thu, 1 Aug 2024 19:22:52 +0200 Subject: [PATCH 110/180] [Mailer] Implement Postal mailer --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/mailer_transports.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 49821a043..35784d3ee 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2642,6 +2642,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co 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\Postal\Transport\PostalTransportFactory::class => 'mailer.transport_factory.postal', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', MailerBridge\Resend\Transport\ResendTransportFactory::class => 'mailer.transport_factory.resend', MailerBridge\Scaleway\Transport\ScalewayTransportFactory::class => 'mailer.transport_factory.scaleway', diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index bdcd7e9c6..34e688532 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -22,6 +22,7 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; +use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; @@ -57,6 +58,7 @@ 'mailpace' => MailPaceTransportFactory::class, 'native' => NativeTransportFactory::class, 'null' => NullTransportFactory::class, + 'postal' => PostalTransportFactory::class, 'postmark' => PostmarkTransportFactory::class, 'resend' => ResendTransportFactory::class, 'scaleway' => ScalewayTransportFactory::class, From 711af4eefcb4054a9c93e44b403626e1826bcddd Mon Sep 17 00:00:00 2001 From: HypeMC Date: Sun, 11 Aug 2024 18:10:02 +0200 Subject: [PATCH 111/180] [FrameworkBundle] Re-remove redundant name attribute from `default_context` --- DependencyInjection/Configuration.php | 1 - 1 file changed, 1 deletion(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 1094c14d3..2e9cacaa8 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1118,7 +1118,6 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e ->end() ->arrayNode('default_context') ->normalizeKeys(false) - ->useAttributeAsKey('name') ->validate() ->ifTrue(fn () => $this->debug && class_exists(JsonParser::class)) ->then(fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) From 6dd1dab4040a0022eb22f44bc07f12a551fd5449 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 6 Aug 2024 09:58:47 +0200 Subject: [PATCH 112/180] [FrameworkBundle] Deprecate making `cache.app` adapter taggable --- CHANGELOG.md | 1 + DependencyInjection/FrameworkExtension.php | 5 +++++ .../Fixtures/php/cache_cacheapp_tagaware.php | 16 ++++++++++++++++ .../Fixtures/xml/cache_cacheapp_tagaware.xml | 15 +++++++++++++++ .../Fixtures/yml/cache_cacheapp_tagaware.yml | 11 +++++++++++ .../FrameworkExtensionTestCase.php | 13 +++++++++++++ 6 files changed, 61 insertions(+) create mode 100644 Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php create mode 100644 Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml create mode 100644 Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7058a3fb2..62eab0457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * Make the `config/` directory optional in `MicroKernelTrait`, add support for service arguments in the invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing * [BC BREAK] The `secrets:decrypt-to-local` command terminates with a non-zero exit code when a secret could not be read + * Deprecate making `cache.app` adapter taggable, use the `cache.app.taggable` adapter instead 7.1 --- diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 067e631c7..e79dba300 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2363,6 +2363,11 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con ]; } foreach ($config['pools'] as $name => $pool) { + if (\in_array('cache.app', $pool['adapters'] ?? [], true) && $pool['tags']) { + trigger_deprecation('symfony/framework-bundle', '7.2', 'Using the "tags" option with the "cache.app" adapter is deprecated. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); + // throw new LogicException('The "tags" option cannot be used with the "cache.app" adapter. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); + } + $pool['adapters'] = $pool['adapters'] ?: ['cache.app']; $isRedisTagAware = ['cache.adapter.redis_tag_aware'] === $pool['adapters']; diff --git a/Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php b/Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php new file mode 100644 index 000000000..77606f5b1 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php @@ -0,0 +1,16 @@ +loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'cache' => [ + 'pools' => [ + 'app.tagaware' => [ + 'adapter' => 'cache.app', + 'tags' => true, + ], + ], + ], +]); diff --git a/Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml b/Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml new file mode 100644 index 000000000..7d59e19d5 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml b/Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml new file mode 100644 index 000000000..32ef3d49c --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml @@ -0,0 +1,11 @@ +framework: + annotations: false + http_method_override: false + handle_all_throwables: true + php_errors: + log: true + cache: + pools: + app.tagaware: + adapter: cache.app + tags: true diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index b37d2e910..d71237c5d 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -13,6 +13,7 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; @@ -93,6 +94,8 @@ abstract class FrameworkExtensionTestCase extends TestCase { + use ExpectDeprecationTrait; + private static array $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); @@ -1833,6 +1836,16 @@ public function testCacheTaggableTagAppliedToPools() } } + /** + * @group legacy + */ + public function testTaggableCacheAppIsDeprecated() + { + $this->expectDeprecation('Since symfony/framework-bundle 7.2: Using the "tags" option with the "cache.app" adapter is deprecated. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); + + $this->createContainerFromFile('cache_cacheapp_tagaware'); + } + /** * @dataProvider appRedisTagAwareConfigProvider */ From e1949dafd4796882f5b378deb01b56d9a1d91d6d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 23 Jul 2024 08:39:50 +0200 Subject: [PATCH 113/180] [FrameworkBundle] enable detailed error messages by default when debug enabled --- CHANGELOG.md | 1 + DependencyInjection/Configuration.php | 4 ++++ .../DependencyInjection/ConfigurationTest.php | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62eab0457..c9edde83a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing * [BC BREAK] The `secrets:decrypt-to-local` command terminates with a non-zero exit code when a secret could not be read * Deprecate making `cache.app` adapter taggable, use the `cache.app.taggable` adapter instead + * Enable `json_decode_detailed_errors` in the default serializer context in debug mode by default when `seld/jsonlint` is installed 7.1 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 42181d7ac..ed7aff374 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1126,6 +1126,10 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e ->prototype('variable')->end() ->end() ->end() + ->validate() + ->ifTrue(fn ($v) => $this->debug && class_exists(JsonParser::class) && !isset($v['default_context'][JsonDecode::DETAILED_ERROR_MESSAGES])) + ->then(function ($v) { $v['default_context'][JsonDecode::DETAILED_ERROR_MESSAGES] = true; return $v; }) + ->end() ->end() ->end() ; diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index bad27f8ee..948df2cd9 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -673,6 +673,30 @@ public function testScopedHttpClientsInheritRateLimiterAndRetryFailedConfigurati $this->assertSame(999, $scopedClients['qux']['retry_failed']['delay']); } + public function testSerializerJsonDetailedErrorMessagesEnabledByDefaultWithDebugEnabled() + { + $processor = new Processor(); + $config = $processor->processConfiguration(new Configuration(true), [ + [ + 'serializer' => null, + ], + ]); + + $this->assertSame([JsonDecode::DETAILED_ERROR_MESSAGES => true], $config['serializer']['default_context'] ?? []); + } + + public function testSerializerJsonDetailedErrorMessagesNotSetByDefaultWithDebugDisabled() + { + $processor = new Processor(); + $config = $processor->processConfiguration(new Configuration(false), [ + [ + 'serializer' => null, + ], + ]); + + $this->assertSame([], $config['serializer']['default_context'] ?? []); + } + protected static function getBundleDefaultConfig() { return [ From 6a9d887df947cd3c765725c6f35dcf82741bfdb7 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 29 Jun 2024 20:46:00 +0200 Subject: [PATCH 114/180] decouple the Webhook component from the Serializer component --- DependencyInjection/FrameworkExtension.php | 15 +++++---------- Resources/config/webhook.php | 9 +++++++++ Tests/DependencyInjection/ConfigurationTest.php | 6 ++++-- .../FrameworkExtensionTestCase.php | 8 ++------ composer.json | 2 ++ 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 49821a043..e784329dd 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -548,7 +548,7 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerProfilerConfiguration($config['profiler'], $container, $loader); if ($this->readConfigEnabled('webhook', $container, $config['webhook'])) { - $this->registerWebhookConfiguration($config['webhook'], $container, $loader); + $this->registerWebhookConfiguration($config['webhook'], $container, $loader, $this->readConfigEnabled('serializer', $container, $config['serializer'])); // If Webhook is installed but the HttpClient or Serializer components are not available, we should throw an error if (!$this->readConfigEnabled('http_client', $container, $config['http_client'])) { @@ -559,14 +559,6 @@ public function load(array $configs, ContainerBuilder $container): void ) ->addTag('container.error'); } - if (!$this->readConfigEnabled('serializer', $container, $config['serializer'])) { - $container->getDefinition('webhook.body_configurator.json') - ->setArguments([]) - ->addError('You cannot use the "webhook transport" service since the Serializer component is not ' - .(class_exists(Serializer::class) ? 'enabled. Try setting "framework.serializer.enabled" to true.' : 'installed. Try running "composer require symfony/serializer-pack".') - ) - ->addTag('container.error'); - } } if ($this->readConfigEnabled('remote-event', $container, $config['remote-event'])) { @@ -2919,7 +2911,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ } } - private function registerWebhookConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void + private function registerWebhookConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $serializerEnabled): void { if (!class_exists(WebhookController::class)) { throw new LogicException('Webhook support cannot be enabled as the component is not installed. Try running "composer require symfony/webhook".'); @@ -2938,6 +2930,9 @@ private function registerWebhookConfiguration(array $config, ContainerBuilder $c $controller = $container->getDefinition('webhook.controller'); $controller->replaceArgument(0, $parsers); $controller->replaceArgument(1, new Reference($config['message_bus'])); + + $jsonBodyConfigurator = $container->getDefinition('webhook.body_configurator.json'); + $jsonBodyConfigurator->replaceArgument(0, new Reference($serializerEnabled ? 'webhook.payload_serializer.serializer' : 'webhook.payload_serializer.json')); } private function registerRemoteEventConfiguration(PhpFileLoader $loader): void diff --git a/Resources/config/webhook.php b/Resources/config/webhook.php index a7e9d58ce..85cf9bb40 100644 --- a/Resources/config/webhook.php +++ b/Resources/config/webhook.php @@ -17,6 +17,8 @@ use Symfony\Component\Webhook\Server\HeadersConfigurator; use Symfony\Component\Webhook\Server\HeaderSignatureConfigurator; use Symfony\Component\Webhook\Server\JsonBodyConfigurator; +use Symfony\Component\Webhook\Server\NativeJsonPayloadSerializer; +use Symfony\Component\Webhook\Server\SerializerPayloadSerializer; use Symfony\Component\Webhook\Server\Transport; return static function (ContainerConfigurator $container) { @@ -32,6 +34,13 @@ ->set('webhook.headers_configurator', HeadersConfigurator::class) ->set('webhook.body_configurator.json', JsonBodyConfigurator::class) + ->args([ + abstract_arg('payload serializer'), + ]) + + ->set('webhook.payload_serializer.json', NativeJsonPayloadSerializer::class) + + ->set('webhook.payload_serializer.serializer', SerializerPayloadSerializer::class) ->args([ service('serializer'), ]) diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 793be0283..1aee05646 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -27,10 +27,12 @@ use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Notifier\Notifier; use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter; +use Symfony\Component\RemoteEvent\RemoteEvent; use Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory; use Symfony\Component\Serializer\Encoder\JsonDecode; use Symfony\Component\TypeInfo\Type; use Symfony\Component\Uid\Factory\UuidFactory; +use Symfony\Component\Webhook\Controller\WebhookController; class ConfigurationTest extends TestCase { @@ -925,12 +927,12 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], 'exceptions' => [], 'webhook' => [ - 'enabled' => false, + 'enabled' => !class_exists(FullStack::class) && class_exists(WebhookController::class), 'routing' => [], 'message_bus' => 'messenger.default_bus', ], 'remote-event' => [ - 'enabled' => false, + 'enabled' => !class_exists(FullStack::class) && class_exists(RemoteEvent::class), ], ]; } diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index b37d2e910..dc35d0f86 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -2357,7 +2357,7 @@ public function testWebhook() $this->assertSame(RequestParser::class, $container->getDefinition('webhook.request_parser')->getClass()); $this->assertFalse($container->getDefinition('webhook.transport')->hasErrors()); - $this->assertFalse($container->getDefinition('webhook.body_configurator.json')->hasErrors()); + $this->assertEquals('webhook.payload_serializer.serializer', $container->getDefinition('webhook.body_configurator.json')->getArgument(0)); } public function testWebhookWithoutSerializer() @@ -2369,11 +2369,7 @@ public function testWebhookWithoutSerializer() $container = $this->createContainerFromFile('webhook_without_serializer'); $this->assertFalse($container->getDefinition('webhook.transport')->hasErrors()); - $this->assertTrue($container->getDefinition('webhook.body_configurator.json')->hasErrors()); - $this->assertSame( - ['You cannot use the "webhook transport" service since the Serializer component is not enabled. Try setting "framework.serializer.enabled" to true.'], - $container->getDefinition('webhook.body_configurator.json')->getErrors() - ); + $this->assertEquals('webhook.payload_serializer.json', $container->getDefinition('webhook.body_configurator.json')->getArgument(0)); } public function testAssetMapperWithoutAssets() diff --git a/composer.json b/composer.json index af934f35d..5e27ec62c 100644 --- a/composer.json +++ b/composer.json @@ -71,6 +71,7 @@ "symfony/property-info": "^6.4|^7.0", "symfony/uid": "^6.4|^7.0", "symfony/web-link": "^6.4|^7.0", + "symfony/webhook": "^7.2", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "twig/twig": "^3.0.4" }, @@ -102,6 +103,7 @@ "symfony/twig-bundle": "<6.4", "symfony/validator": "<6.4", "symfony/web-profiler-bundle": "<6.4", + "symfony/webhook": "<7.2", "symfony/workflow": "<6.4" }, "autoload": { From 1fc8184b44eb05359dc2b25abed5ee87ecb53d39 Mon Sep 17 00:00:00 2001 From: Mathieu Santostefano Date: Mon, 17 Jun 2024 20:02:47 +0200 Subject: [PATCH 115/180] Add Sweego Mailer Bridge --- DependencyInjection/FrameworkExtension.php | 2 ++ Resources/config/mailer_transports.php | 2 ++ Resources/config/mailer_webhook.php | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index b773c9860..dd8a0777c 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2645,6 +2645,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co 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', ]; foreach ($classToServices as $class => $service) { @@ -2665,6 +2666,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Postmark\Webhook\PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark', 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', ]; foreach ($webhookRequestParsers as $class => $service) { diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index 34e688532..8c7131b79 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -27,6 +27,7 @@ use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; +use Symfony\Component\Mailer\Bridge\Sweego\Transport\SweegoTransportFactory; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\NativeTransportFactory; use Symfony\Component\Mailer\Transport\NullTransportFactory; @@ -65,6 +66,7 @@ 'sendgrid' => SendgridTransportFactory::class, 'sendmail' => SendmailTransportFactory::class, 'smtp' => EsmtpTransportFactory::class, + 'sweego' => SweegoTransportFactory::class, ]; foreach ($factories as $name => $class) { diff --git a/Resources/config/mailer_webhook.php b/Resources/config/mailer_webhook.php index 64020c1b1..f0a50800f 100644 --- a/Resources/config/mailer_webhook.php +++ b/Resources/config/mailer_webhook.php @@ -27,6 +27,8 @@ use Symfony\Component\Mailer\Bridge\Resend\Webhook\ResendRequestParser; use Symfony\Component\Mailer\Bridge\Sendgrid\RemoteEvent\SendgridPayloadConverter; use Symfony\Component\Mailer\Bridge\Sendgrid\Webhook\SendgridRequestParser; +use Symfony\Component\Mailer\Bridge\Sweego\RemoteEvent\SweegoPayloadConverter; +use Symfony\Component\Mailer\Bridge\Sweego\Webhook\SweegoRequestParser; return static function (ContainerConfigurator $container) { $container->services() @@ -69,5 +71,10 @@ ->set('mailer.webhook.request_parser.sendgrid', SendgridRequestParser::class) ->args([service('mailer.payload_converter.sendgrid')]) ->alias(SendgridRequestParser::class, 'mailer.webhook.request_parser.sendgrid') + + ->set('mailer.payload_converter.sweego', SweegoPayloadConverter::class) + ->set('mailer.webhook.request_parser.sweego', SweegoRequestParser::class) + ->args([service('mailer.payload_converter.sweego')]) + ->alias(SweegoRequestParser::class, 'mailer.webhook.request_parser.sweego') ; }; From eaad4d43143db46e08f0f80334cfe8948c49c06d Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Sat, 17 Aug 2024 09:09:39 +0200 Subject: [PATCH 116/180] [FrameworkBundle] Fix comment --- DependencyInjection/FrameworkExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index b773c9860..8f659f657 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -550,7 +550,7 @@ public function load(array $configs, ContainerBuilder $container): void if ($this->readConfigEnabled('webhook', $container, $config['webhook'])) { $this->registerWebhookConfiguration($config['webhook'], $container, $loader, $this->readConfigEnabled('serializer', $container, $config['serializer'])); - // If Webhook is installed but the HttpClient or Serializer components are not available, we should throw an error + // If Webhook is installed but the HttpClient component is not available, we should throw an error if (!$this->readConfigEnabled('http_client', $container, $config['http_client'])) { $container->getDefinition('webhook.transport') ->setArguments([]) From 4c523688dadef21a2660819f961556930121c161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 22 Aug 2024 11:18:18 +0200 Subject: [PATCH 117/180] [Serializer] Add SnakeCaseToCamelCaseNameConverter --- CHANGELOG.md | 1 + DependencyInjection/FrameworkExtension.php | 6 ++++++ Resources/config/serializer.php | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9edde83a..193f4570c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ CHANGELOG * [BC BREAK] The `secrets:decrypt-to-local` command terminates with a non-zero exit code when a secret could not be read * Deprecate making `cache.app` adapter taggable, use the `cache.app.taggable` adapter instead * Enable `json_decode_detailed_errors` in the default serializer context in debug mode by default when `seld/jsonlint` is installed + * Register `Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter` as a service named `serializer.name_converter.snake_case_to_camel_case` if available 7.1 --- diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index a44e9a25b..d7c4403b0 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -158,6 +158,7 @@ use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; +use Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Serializer; @@ -1849,6 +1850,11 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->removeDefinition('serializer.normalizer.mime_message'); } + // BC layer Serializer < 7.2 + if (!class_exists(SnakeCaseToCamelCaseNameConverter::class)) { + $container->removeDefinition('serializer.name_converter.snake_case_to_camel_case'); + } + if ($container->getParameter('kernel.debug')) { $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); } diff --git a/Resources/config/serializer.php b/Resources/config/serializer.php index c75776900..36c8b89b5 100644 --- a/Resources/config/serializer.php +++ b/Resources/config/serializer.php @@ -31,6 +31,7 @@ use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter; +use Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer; use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer; @@ -186,8 +187,9 @@ ->set('serializer.encoder.csv', CsvEncoder::class) ->tag('serializer.encoder') - // Name converter + // Name converters ->set('serializer.name_converter.camel_case_to_snake_case', CamelCaseToSnakeCaseNameConverter::class) + ->set('serializer.name_converter.snake_case_to_camel_case', SnakeCaseToCamelCaseNameConverter::class) ->set('serializer.name_converter.metadata_aware', MetadataAwareNameConverter::class) ->args([service('serializer.mapping.class_metadata_factory')]) From 4d9f5d3c52135246aa5a96452c9f7e43f3f54783 Mon Sep 17 00:00:00 2001 From: Ahmed Ghanem Date: Mon, 8 Jul 2024 01:50:11 +0300 Subject: [PATCH 118/180] [Notifier] Support for desktop notifications via `jolicode/JoliNotif` --- DependencyInjection/FrameworkExtension.php | 2 ++ Resources/config/notifier.php | 10 ++++++++++ Resources/config/notifier_transports.php | 1 + 3 files changed, 13 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index d7c4403b0..75cfe1d1f 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2766,6 +2766,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ } $container->getDefinition('notifier.channel.sms')->setArgument(0, null); $container->getDefinition('notifier.channel.push')->setArgument(0, null); + $container->getDefinition('notifier.channel.desktop')->setArgument(0, null); } $container->getDefinition('notifier.channel_policy')->setArgument(0, $config['channel_policy']); @@ -2801,6 +2802,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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\LineNotify\LineNotifyTransportFactory::class => 'notifier.transport_factory.line-notify', diff --git a/Resources/config/notifier.php b/Resources/config/notifier.php index 3bd19b8dd..95a4d12e9 100644 --- a/Resources/config/notifier.php +++ b/Resources/config/notifier.php @@ -15,6 +15,7 @@ use Symfony\Component\Notifier\Channel\BrowserChannel; use Symfony\Component\Notifier\Channel\ChannelPolicy; use Symfony\Component\Notifier\Channel\ChatChannel; +use Symfony\Component\Notifier\Channel\DesktopChannel; use Symfony\Component\Notifier\Channel\EmailChannel; use Symfony\Component\Notifier\Channel\PushChannel; use Symfony\Component\Notifier\Channel\SmsChannel; @@ -24,6 +25,7 @@ use Symfony\Component\Notifier\EventListener\SendFailedMessageToNotifierListener; use Symfony\Component\Notifier\FlashMessage\DefaultFlashMessageImportanceMapper; use Symfony\Component\Notifier\Message\ChatMessage; +use Symfony\Component\Notifier\Message\DesktopMessage; use Symfony\Component\Notifier\Message\PushMessage; use Symfony\Component\Notifier\Message\SmsMessage; use Symfony\Component\Notifier\Messenger\MessageHandler; @@ -76,6 +78,10 @@ ->args([service('texter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) ->tag('notifier.channel', ['channel' => 'push']) + ->set('notifier.channel.desktop', DesktopChannel::class) + ->args([service('texter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) + ->tag('notifier.channel', ['channel' => 'desktop']) + ->set('notifier.monolog_handler', NotifierHandler::class) ->args([service('notifier')]) @@ -126,6 +132,10 @@ ->args([service('texter.transports')]) ->tag('messenger.message_handler', ['handles' => PushMessage::class]) + ->set('texter.messenger.desktop_handler', MessageHandler::class) + ->args([service('texter.transports')]) + ->tag('messenger.message_handler', ['handles' => DesktopMessage::class]) + ->set('notifier.notification_logger_listener', NotificationLoggerListener::class) ->tag('kernel.event_subscriber') diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index a773899f7..7c8002993 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -72,6 +72,7 @@ 'infobip' => Bridge\Infobip\InfobipTransportFactory::class, 'iqsms' => Bridge\Iqsms\IqsmsTransportFactory::class, 'isendpro' => Bridge\Isendpro\IsendproTransportFactory::class, + 'joli-notif' => Bridge\JoliNotif\JoliNotifTransportFactory::class, 'kaz-info-teh' => Bridge\KazInfoTeh\KazInfoTehTransportFactory::class, 'light-sms' => Bridge\LightSms\LightSmsTransportFactory::class, 'lox24' => Bridge\Lox24\Lox24TransportFactory::class, From bfd6ef6c982ac04c5b786a4b636088464687e767 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 27 Aug 2024 09:19:01 +0200 Subject: [PATCH 119/180] [FrameworkBundle] Fix low-deps tests --- Resources/config/notifier.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Resources/config/notifier.php b/Resources/config/notifier.php index 95a4d12e9..04fa4ce51 100644 --- a/Resources/config/notifier.php +++ b/Resources/config/notifier.php @@ -132,12 +132,14 @@ ->args([service('texter.transports')]) ->tag('messenger.message_handler', ['handles' => PushMessage::class]) - ->set('texter.messenger.desktop_handler', MessageHandler::class) - ->args([service('texter.transports')]) - ->tag('messenger.message_handler', ['handles' => DesktopMessage::class]) - ->set('notifier.notification_logger_listener', NotificationLoggerListener::class) ->tag('kernel.event_subscriber') - ; + + if (class_exists(DesktopMessage::class)) { + $container->services() + ->set('texter.messenger.desktop_handler', MessageHandler::class) + ->args([service('texter.transports')]) + ->tag('messenger.message_handler', ['handles' => DesktopMessage::class]); + } }; From a63613f379dd5261113be7abd51de74ca826248f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 29 Aug 2024 10:25:47 +0200 Subject: [PATCH 120/180] bump requirement for Twig to 3.12+ --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5e27ec62c..50672edb9 100644 --- a/composer.json +++ b/composer.json @@ -73,7 +73,7 @@ "symfony/web-link": "^6.4|^7.0", "symfony/webhook": "^7.2", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^3.0.4" + "twig/twig": "^3.12" }, "conflict": { "doctrine/persistence": "<1.3", From d2b3f073884f675f748b49fac2fb8234557832f6 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sat, 31 Aug 2024 00:31:12 +0200 Subject: [PATCH 121/180] CS: re-apply `trailing_comma_in_multiline` --- .../php/messenger_multiple_failure_transports.php | 6 +++--- .../php/messenger_multiple_failure_transports_global.php | 4 ++-- .../Fixtures/php/messenger_transports.php | 2 +- Tests/DependencyInjection/Fixtures/php/notifier.php | 8 ++++---- .../Fixtures/php/notifier_with_disabled_message_bus.php | 4 ++-- .../Fixtures/php/notifier_with_specific_message_bus.php | 4 ++-- .../Fixtures/php/notifier_without_mailer.php | 6 +++--- .../Fixtures/php/notifier_without_messenger.php | 6 +++--- Tests/DependencyInjection/Fixtures/php/profiler.php | 2 +- .../Fixtures/php/profiler_collect_serializer_data.php | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php b/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php index 88a4a8073..1fa698076 100644 --- a/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php +++ b/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php @@ -9,15 +9,15 @@ 'transports' => [ 'transport_1' => [ 'dsn' => 'null://', - 'failure_transport' => 'failure_transport_1' + 'failure_transport' => 'failure_transport_1', ], 'transport_2' => 'null://', 'transport_3' => [ 'dsn' => 'null://', - 'failure_transport' => 'failure_transport_3' + 'failure_transport' => 'failure_transport_3', ], 'failure_transport_1' => 'null://', - 'failure_transport_3' => 'null://' + 'failure_transport_3' => 'null://', ], ], ]); diff --git a/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php b/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php index 9f794556b..763db88a8 100644 --- a/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php +++ b/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php @@ -10,12 +10,12 @@ 'transports' => [ 'transport_1' => [ 'dsn' => 'null://', - 'failure_transport' => 'failure_transport_1' + 'failure_transport' => 'failure_transport_1', ], 'transport_2' => 'null://', 'transport_3' => [ 'dsn' => 'null://', - 'failure_transport' => 'failure_transport_3' + 'failure_transport' => 'failure_transport_3', ], 'failure_transport_global' => 'null://', 'failure_transport_1' => 'null://', diff --git a/Tests/DependencyInjection/Fixtures/php/messenger_transports.php b/Tests/DependencyInjection/Fixtures/php/messenger_transports.php index bba32ce0b..a010da534 100644 --- a/Tests/DependencyInjection/Fixtures/php/messenger_transports.php +++ b/Tests/DependencyInjection/Fixtures/php/messenger_transports.php @@ -23,7 +23,7 @@ 'multiplier' => 3, 'max_delay' => 100, ], - 'rate_limiter' => 'customised_worker' + 'rate_limiter' => 'customised_worker', ], 'failed' => 'in-memory:///', 'redis' => 'redis://127.0.0.1:6379/messages', diff --git a/Tests/DependencyInjection/Fixtures/php/notifier.php b/Tests/DependencyInjection/Fixtures/php/notifier.php index 0def62cac..9abf2c880 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier.php @@ -9,7 +9,7 @@ 'handle_all_throwables' => true, 'php_errors' => ['log' => true], 'messenger' => [ - 'enabled' => true + 'enabled' => true, ], 'mailer' => [ 'dsn' => 'smtp://example.com', @@ -18,10 +18,10 @@ 'enabled' => true, 'notification_on_failed_messages' => true, 'chatter_transports' => [ - 'slack' => 'null' + 'slack' => 'null', ], 'texter_transports' => [ - 'twilio' => 'null' + 'twilio' => 'null', ], 'channel_policy' => [ 'low' => ['slack'], @@ -29,6 +29,6 @@ ], 'admin_recipients' => [ ['email' => 'test@test.de', 'phone' => '+490815',], - ] + ], ], ]); diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_with_disabled_message_bus.php b/Tests/DependencyInjection/Fixtures/php/notifier_with_disabled_message_bus.php index 6b9b4ff07..8c6b2f002 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_with_disabled_message_bus.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_with_disabled_message_bus.php @@ -14,10 +14,10 @@ 'notifier' => [ 'message_bus' => false, 'chatter_transports' => [ - 'test' => 'null' + 'test' => 'null', ], 'texter_transports' => [ - 'test' => 'null' + 'test' => 'null', ], ], ]); diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_with_specific_message_bus.php b/Tests/DependencyInjection/Fixtures/php/notifier_with_specific_message_bus.php index f8b4ad66d..4c38323bd 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_with_specific_message_bus.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_with_specific_message_bus.php @@ -14,10 +14,10 @@ 'notifier' => [ 'message_bus' => 'app.another_bus', 'chatter_transports' => [ - 'test' => 'null' + 'test' => 'null', ], 'texter_transports' => [ - 'test' => 'null' + 'test' => 'null', ], ], ]); diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php b/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php index 5967dcb9e..fbb988527 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php @@ -18,10 +18,10 @@ 'enabled' => true, 'notification_on_failed_messages' => true, 'chatter_transports' => [ - 'slack' => 'null' + 'slack' => 'null', ], 'texter_transports' => [ - 'twilio' => 'null' + 'twilio' => 'null', ], 'channel_policy' => [ 'low' => ['slack'], @@ -29,6 +29,6 @@ ], 'admin_recipients' => [ ['email' => 'test@test.de', 'phone' => '+490815',], - ] + ], ], ]); diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php b/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php index 4a477e008..454f8ccec 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php @@ -18,10 +18,10 @@ 'enabled' => true, 'notification_on_failed_messages' => true, 'chatter_transports' => [ - 'slack' => 'null' + 'slack' => 'null', ], 'texter_transports' => [ - 'twilio' => 'null' + 'twilio' => 'null', ], 'channel_policy' => [ 'low' => ['slack'], @@ -29,7 +29,7 @@ ], 'admin_recipients' => [ ['email' => 'test@test.de', 'phone' => '+490815',], - ] + ], ], 'scheduler' => false, ]); diff --git a/Tests/DependencyInjection/Fixtures/php/profiler.php b/Tests/DependencyInjection/Fixtures/php/profiler.php index 43a7a002c..faf76bbc7 100644 --- a/Tests/DependencyInjection/Fixtures/php/profiler.php +++ b/Tests/DependencyInjection/Fixtures/php/profiler.php @@ -9,6 +9,6 @@ 'enabled' => true, ], 'serializer' => [ - 'enabled' => true + 'enabled' => true, ], ]); diff --git a/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php b/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php index 1fb869a80..99e2a52cf 100644 --- a/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php +++ b/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php @@ -11,5 +11,5 @@ ], 'serializer' => [ 'enabled' => true, - ] + ], ]); From 78e8f4344088f60d92120b1e48bad93e144cf251 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 2 Sep 2024 14:07:48 +0200 Subject: [PATCH 122/180] Fix configurations info consistency --- DependencyInjection/Configuration.php | 120 +++++++++++++------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index ed7aff374..bbdfb1e03 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -85,7 +85,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->children() ->scalarNode('secret')->end() ->booleanNode('http_method_override') - ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") + ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead.") ->defaultFalse() ->end() ->scalarNode('trust_x_sendfile_type_header') @@ -132,7 +132,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarNode('error_controller') ->defaultValue('error_controller') ->end() - ->booleanNode('handle_all_throwables')->info('HttpKernel will handle all kinds of \Throwable')->defaultTrue()->end() + ->booleanNode('handle_all_throwables')->info('HttpKernel will handle all kinds of \Throwable.')->defaultTrue()->end() ->end() ; @@ -226,7 +226,7 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI $rootNode ->children() ->arrayNode('form') - ->info('form configuration') + ->info('Form configuration') ->{$enableIfStandalone('symfony/form', Form::class)}() ->children() ->arrayNode('csrf_protection') @@ -284,7 +284,7 @@ private function addEsiSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('esi') - ->info('esi configuration') + ->info('ESI configuration') ->canBeEnabled() ->end() ->end() @@ -296,7 +296,7 @@ private function addSsiSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('ssi') - ->info('ssi configuration') + ->info('SSI configuration') ->canBeEnabled() ->end() ->end(); @@ -307,7 +307,7 @@ private function addFragmentsSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('fragments') - ->info('fragments configuration') + ->info('Fragments configuration') ->canBeEnabled() ->children() ->scalarNode('hinclude_default_template')->defaultNull()->end() @@ -323,15 +323,15 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('profiler') - ->info('profiler configuration') + ->info('Profiler configuration') ->canBeEnabled() ->children() ->booleanNode('collect')->defaultTrue()->end() - ->scalarNode('collect_parameter')->defaultNull()->info('The name of the parameter to use to enable or disable collection on a per request basis')->end() + ->scalarNode('collect_parameter')->defaultNull()->info('The name of the parameter to use to enable or disable collection on a per request basis.')->end() ->booleanNode('only_exceptions')->defaultFalse()->end() ->booleanNode('only_main_requests')->defaultFalse()->end() ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() - ->booleanNode('collect_serializer_data')->info('Enables the serializer data collector and profiler panel')->defaultFalse()->end() + ->booleanNode('collect_serializer_data')->info('Enables the serializer data collector and profiler panel.')->defaultFalse()->end() ->end() ->end() ->end() @@ -450,7 +450,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void }) ->thenInvalid('The value must be "null" or an array of workflow events (like ["workflow.enter"]).') ->end() - ->info('Select which Transition events should be dispatched for this Workflow') + ->info('Select which Transition events should be dispatched for this Workflow.') ->example(['workflow.enter', 'workflow.transition']) ->end() ->arrayNode('places') @@ -534,7 +534,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->end() ->scalarNode('guard') ->cannotBeEmpty() - ->info('An expression to block the transition') + ->info('An expression to block the transition.') ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') ->end() ->arrayNode('from') @@ -612,7 +612,7 @@ private function addRouterSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('router') - ->info('router configuration') + ->info('Router configuration') ->canBeEnabled() ->children() ->scalarNode('resource')->isRequired()->end() @@ -622,7 +622,7 @@ private function addRouterSection(ArrayNodeDefinition $rootNode): void ->setDeprecated('symfony/framework-bundle', '7.1', 'Setting the "%path%.%node%" configuration option is deprecated. It will be removed in version 8.0.') ->end() ->scalarNode('default_uri') - ->info('The default URI used to generate URLs in a non-HTTP context') + ->info('The default URI used to generate URLs in a non-HTTP context.') ->defaultNull() ->end() ->scalarNode('http_port')->defaultValue(80)->end() @@ -648,7 +648,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('session') - ->info('session configuration') + ->info('Session configuration') ->canBeEnabled() ->children() ->scalarNode('storage_factory_id')->defaultValue('session.storage.factory.native')->end() @@ -676,11 +676,11 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void ->scalarNode('gc_probability')->defaultValue(1)->end() ->scalarNode('gc_maxlifetime')->end() ->scalarNode('save_path') - ->info('Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null') + ->info('Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null.') ->end() ->integerNode('metadata_update_threshold') ->defaultValue(0) - ->info('seconds to wait between 2 session metadata updates') + ->info('Seconds to wait between 2 session metadata updates.') ->end() ->integerNode('sid_length') ->min(22) @@ -701,7 +701,7 @@ private function addRequestSection(ArrayNodeDefinition $rootNode): void $rootNode ->children() ->arrayNode('request') - ->info('request configuration') + ->info('Request configuration') ->canBeEnabled() ->fixXmlConfig('format') ->children() @@ -727,12 +727,12 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl $rootNode ->children() ->arrayNode('assets') - ->info('assets configuration') + ->info('Assets configuration') ->{$enableIfStandalone('symfony/asset', Package::class)}() ->fixXmlConfig('base_url') ->children() ->booleanNode('strict_mode') - ->info('Throw an exception if an entry is missing from the manifest.json') + ->info('Throw an exception if an entry is missing from the manifest.json.') ->defaultFalse() ->end() ->scalarNode('version_strategy')->defaultNull()->end() @@ -773,7 +773,7 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl ->fixXmlConfig('base_url') ->children() ->booleanNode('strict_mode') - ->info('Throw an exception if an entry is missing from the manifest.json') + ->info('Throw an exception if an entry is missing from the manifest.json.') ->defaultFalse() ->end() ->scalarNode('version_strategy')->defaultNull()->end() @@ -832,7 +832,7 @@ private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $ ->children() // add array node called "paths" that will be an array of strings ->arrayNode('paths') - ->info('Directories that hold assets that should be in the mapper. Can be a simple array of an array of ["path/to/assets": "namespace"]') + ->info('Directories that hold assets that should be in the mapper. Can be a simple array of an array of ["path/to/assets": "namespace"].') ->example(['assets/']) ->normalizeKeys(false) ->useAttributeAsKey('namespace') @@ -863,21 +863,21 @@ private function addAssetMapperSection(ArrayNodeDefinition $rootNode, callable $ ->prototype('scalar')->end() ->end() ->arrayNode('excluded_patterns') - ->info('Array of glob patterns of asset file paths that should not be in the asset mapper') + ->info('Array of glob patterns of asset file paths that should not be in the asset mapper.') ->prototype('scalar')->end() ->example(['*/assets/build/*', '*/*_.scss']) ->end() // boolean called defaulting to true ->booleanNode('exclude_dotfiles') - ->info('If true, any files starting with "." will be excluded from the asset mapper') + ->info('If true, any files starting with "." will be excluded from the asset mapper.') ->defaultTrue() ->end() ->booleanNode('server') - ->info('If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default)') + ->info('If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default).') ->defaultValue($this->debug) ->end() ->scalarNode('public_prefix') - ->info('The public path where the assets will be written to (and served from when "server" is true)') + ->info('The public path where the assets will be written to (and served from when "server" is true).') ->defaultValue('/assets/') ->end() ->enumNode('missing_import_mode') @@ -926,7 +926,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e $rootNode ->children() ->arrayNode('translator') - ->info('translator configuration') + ->info('Translator configuration') ->{$enableIfStandalone('symfony/translation', Translator::class)}() ->fixXmlConfig('fallback') ->fixXmlConfig('path') @@ -942,7 +942,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e ->scalarNode('formatter')->defaultValue('translator.formatter.default')->end() ->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end() ->scalarNode('default_path') - ->info('The default path used to load translations') + ->info('The default path used to load translations.') ->defaultValue('%kernel.project_dir%/translations') ->end() ->arrayNode('paths') @@ -965,7 +965,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e ->end() ->end() ->arrayNode('providers') - ->info('Translation providers you can read/write your translations from') + ->info('Translation providers you can read/write your translations from.') ->useAttributeAsKey('name') ->prototype('array') ->fixXmlConfig('domain') @@ -996,7 +996,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e $rootNode ->children() ->arrayNode('validation') - ->info('validation configuration') + ->info('Validation configuration') ->{$enableIfStandalone('symfony/validator', Validation::class)}() ->children() ->scalarNode('cache')->end() @@ -1100,7 +1100,7 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e $rootNode ->children() ->arrayNode('serializer') - ->info('serializer configuration') + ->info('Serializer configuration') ->{$enableIfStandalone('symfony/serializer', Serializer::class)}() ->children() ->booleanNode('enable_attributes')->{class_exists(FullStack::class) ? 'defaultFalse' : 'defaultTrue'}()->end() @@ -1189,16 +1189,16 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->fixXmlConfig('pool') ->children() ->scalarNode('prefix_seed') - ->info('Used to namespace cache keys when using several apps with the same shared backend') + ->info('Used to namespace cache keys when using several apps with the same shared backend.') ->defaultValue('_%kernel.project_dir%.%kernel.container_class%') ->example('my-application-name/%kernel.environment%') ->end() ->scalarNode('app') - ->info('App related cache pools configuration') + ->info('App related cache pools configuration.') ->defaultValue('cache.adapter.filesystem') ->end() ->scalarNode('system') - ->info('System related cache pools configuration') + ->info('System related cache pools configuration.') ->defaultValue('cache.adapter.system') ->end() ->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools/app')->end() @@ -1247,7 +1247,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->scalarNode('tags')->defaultNull()->end() ->booleanNode('public')->defaultFalse()->end() ->scalarNode('default_lifetime') - ->info('Default lifetime of the pool') + ->info('Default lifetime of the pool.') ->example('"300" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression') ->end() ->scalarNode('provider') @@ -1478,7 +1478,7 @@ private function addWebLinkSection(ArrayNodeDefinition $rootNode, callable $enab $rootNode ->children() ->arrayNode('web_link') - ->info('web links configuration') + ->info('Web links configuration') ->{$enableIfStandalone('symfony/weblink', HttpHeaderSerializer::class)}() ->end() ->end() @@ -1604,17 +1604,17 @@ function ($a) { }) ->end() ->children() - ->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end() + ->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely.')->end() ->integerNode('max_retries')->defaultValue(3)->min(0)->end() - ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() - ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))')->end() - ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() - ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness to apply to the delay (between 0 and 1)')->end() + ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used).')->end() + ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries)).')->end() + ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite).')->end() + ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness to apply to the delay (between 0 and 1).')->end() ->end() ->end() ->scalarNode('rate_limiter') ->defaultNull() - ->info('Rate limiter name to use when processing messages') + ->info('Rate limiter name to use when processing messages.') ->end() ->end() ->end() @@ -1859,13 +1859,13 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->info('The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants.') ->end() ->arrayNode('extra') - ->info('Extra options for specific HTTP client') + ->info('Extra options for specific HTTP client.') ->normalizeKeys(false) ->variablePrototype()->end() ->end() ->scalarNode('rate_limiter') ->defaultNull() - ->info('Rate limiter name to use for throttling requests') + ->info('Rate limiter name to use for throttling requests.') ->end() ->append($this->createHttpClientRetrySection()) ->end() @@ -1999,7 +1999,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->info('The passphrase used to encrypt the "local_pk" file.') ->end() ->scalarNode('ciphers') - ->info('A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') + ->info('A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...).') ->end() ->arrayNode('peer_fingerprint') ->info('Associative array: hashing algorithm => hash(es).') @@ -2011,13 +2011,13 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $e ->end() ->end() ->arrayNode('extra') - ->info('Extra options for specific HTTP client') + ->info('Extra options for specific HTTP client.') ->normalizeKeys(false) ->variablePrototype()->end() ->end() ->scalarNode('rate_limiter') ->defaultNull() - ->info('Rate limiter name to use for throttling requests') + ->info('Rate limiter name to use for throttling requests.') ->end() ->append($this->createHttpClientRetrySection()) ->end() @@ -2048,7 +2048,7 @@ private function createHttpClientRetrySection(): ArrayNodeDefinition }) ->end() ->children() - ->scalarNode('retry_strategy')->defaultNull()->info('service id to override the retry strategy')->end() + ->scalarNode('retry_strategy')->defaultNull()->info('service id to override the retry strategy.')->end() ->arrayNode('http_codes') ->performNoDeepMerging() ->beforeNormalization() @@ -2083,17 +2083,17 @@ private function createHttpClientRetrySection(): ArrayNodeDefinition ->then(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') + ->info('A list of HTTP methods that triggers a retry for this status code. When empty, all methods are retried.') ->end() ->end() ->end() - ->info('A list of HTTP status code that triggers a retry') + ->info('A list of HTTP status code that triggers a retry.') ->end() ->integerNode('max_retries')->defaultValue(3)->min(0)->end() - ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() - ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries)')->end() - ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() - ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness in percent (between 0 and 1) to apply to the delay')->end() + ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used).')->end() + ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries).')->end() + ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite).')->end() + ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness in percent (between 0 and 1) to apply to the delay.')->end() ->end() ; } @@ -2284,35 +2284,35 @@ private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $ ->arrayPrototype() ->children() ->scalarNode('lock_factory') - ->info('The service ID of the lock factory used by this limiter (or null to disable locking)') + ->info('The service ID of the lock factory used by this limiter (or null to disable locking).') ->defaultValue('lock.factory') ->end() ->scalarNode('cache_pool') - ->info('The cache pool to use for storing the current limiter state') + ->info('The cache pool to use for storing the current limiter state.') ->defaultValue('cache.rate_limiter') ->end() ->scalarNode('storage_service') - ->info('The service ID of a custom storage implementation, this precedes any configured "cache_pool"') + ->info('The service ID of a custom storage implementation, this precedes any configured "cache_pool".') ->defaultNull() ->end() ->enumNode('policy') - ->info('The algorithm to be used by this limiter') + ->info('The algorithm to be used by this limiter.') ->isRequired() ->values(['fixed_window', 'token_bucket', 'sliding_window', 'no_limit']) ->end() ->integerNode('limit') - ->info('The maximum allowed hits in a fixed interval or burst') + ->info('The maximum allowed hits in a fixed interval or burst.') ->end() ->scalarNode('interval') ->info('Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).') ->end() ->arrayNode('rate') - ->info('Configures the fill rate if "policy" is set to "token_bucket"') + ->info('Configures the fill rate if "policy" is set to "token_bucket".') ->children() ->scalarNode('interval') ->info('Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).') ->end() - ->integerNode('amount')->info('Amount of tokens to add each interval')->defaultValue(1)->end() + ->integerNode('amount')->info('Amount of tokens to add each interval.')->defaultValue(1)->end() ->end() ->end() ->end() From e3c09d429955e750a0746e4ed0905b47f4f5b559 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Aug 2024 09:35:32 +0200 Subject: [PATCH 123/180] allow Twig 4 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 50672edb9..a6552ca5b 100644 --- a/composer.json +++ b/composer.json @@ -73,7 +73,7 @@ "symfony/web-link": "^6.4|^7.0", "symfony/webhook": "^7.2", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^3.12" + "twig/twig": "^3.12|^4.0" }, "conflict": { "doctrine/persistence": "<1.3", From f7b477a510628b22733e4a454e34c5ab3d2d3b0c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Sep 2024 10:21:02 +0200 Subject: [PATCH 124/180] [HttpFoundation] Add `PRIVATE_SUBNETS` as a shortcut for private IP address ranges to `Request::setTrustedProxies()` --- DependencyInjection/Configuration.php | 6 +++--- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index ed7aff374..44bbe6718 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -111,10 +111,10 @@ public function getConfigTreeBuilder(): TreeBuilder ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() ->prototype('scalar')->end() ->end() - ->scalarNode('trusted_proxies') + ->variableNode('trusted_proxies') ->beforeNormalization() - ->ifTrue(fn ($v) => 'private_ranges' === $v) - ->then(fn ($v) => implode(',', IpUtils::PRIVATE_SUBNETS)) + ->ifTrue(fn ($v) => 'private_ranges' === $v || 'PRIVATE_SUBNETS' === $v) + ->then(fn () => IpUtils::PRIVATE_SUBNETS) ->end() ->end() ->arrayNode('trusted_headers') diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 4b7431fc5..a6da61ae3 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -2354,7 +2354,7 @@ public function testTrustedProxiesWithPrivateRanges() { $container = $this->createContainerFromFile('trusted_proxies_private_ranges'); - $this->assertSame(IpUtils::PRIVATE_SUBNETS, array_map('trim', explode(',', $container->getParameter('kernel.trusted_proxies')))); + $this->assertSame(IpUtils::PRIVATE_SUBNETS, $container->getParameter('kernel.trusted_proxies')); } public function testWebhook() From 8735303b4c22ac46736f168d451e9c5182063f98 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Sep 2024 19:21:15 +0200 Subject: [PATCH 125/180] [FrameworkBundle] Remove default value for gc_probability config option --- DependencyInjection/Configuration.php | 2 +- Tests/DependencyInjection/ConfigurationTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 44bbe6718..aef052eab 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -673,7 +673,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultValue('lax')->end() ->booleanNode('use_cookies')->end() ->scalarNode('gc_divisor')->end() - ->scalarNode('gc_probability')->defaultValue(1)->end() + ->scalarNode('gc_probability')->end() ->scalarNode('gc_maxlifetime')->end() ->scalarNode('save_path') ->info('Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null') diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 820f4bf11..c4c81538c 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -814,7 +814,6 @@ protected static function getBundleDefaultConfig() 'cookie_httponly' => true, 'cookie_samesite' => 'lax', 'cookie_secure' => 'auto', - 'gc_probability' => 1, 'metadata_update_threshold' => 0, ], 'request' => [ From e967c07eade67be68b58caa73e779a3926fc2492 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 8 Sep 2024 18:56:12 +0200 Subject: [PATCH 126/180] Remove obsolete requires annotation --- Tests/Functional/Psr4RoutingTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/Tests/Functional/Psr4RoutingTest.php b/Tests/Functional/Psr4RoutingTest.php index 811a99a11..6104a52ce 100644 --- a/Tests/Functional/Psr4RoutingTest.php +++ b/Tests/Functional/Psr4RoutingTest.php @@ -11,9 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; -/** - * @requires function Symfony\Component\Routing\Loader\Psr4DirectoryLoader::__construct - */ final class Psr4RoutingTest extends AbstractAttributeRoutingTestCase { protected function getTestCaseApp(): string From 2fb5d662fb0cb0c710bb26e525a9405960868385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Geffroy?= <81738559+raphael-geffroy@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:43:15 +0200 Subject: [PATCH 127/180] fix: pass validator.translation_domain to RequestPayloadValueResolver --- Resources/config/web.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/config/web.php b/Resources/config/web.php index 6710dabda..6f8358fb0 100644 --- a/Resources/config/web.php +++ b/Resources/config/web.php @@ -71,6 +71,7 @@ service('serializer'), service('validator')->nullOnInvalid(), service('translator')->nullOnInvalid(), + param('validator.translation_domain'), ]) ->tag('controller.targeted_value_resolver', ['name' => RequestPayloadValueResolver::class]) ->tag('kernel.event_subscriber') From b44cf99da7add4b23ff0b84a1d8111cedf00b8ca Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Sun, 8 Sep 2024 13:05:43 -0400 Subject: [PATCH 128/180] [Mailer] add Mailtrap bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/mailer_transports.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 75cfe1d1f..e6fd4e58e 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2647,6 +2647,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', 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', diff --git a/Resources/config/mailer_transports.php b/Resources/config/mailer_transports.php index 8c7131b79..c0e7cc06a 100644 --- a/Resources/config/mailer_transports.php +++ b/Resources/config/mailer_transports.php @@ -22,6 +22,7 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; +use Symfony\Component\Mailer\Bridge\Mailtrap\Transport\MailtrapTransportFactory; use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; @@ -61,6 +62,7 @@ 'null' => NullTransportFactory::class, 'postal' => PostalTransportFactory::class, 'postmark' => PostmarkTransportFactory::class, + 'mailtrap' => MailtrapTransportFactory::class, 'resend' => ResendTransportFactory::class, 'scaleway' => ScalewayTransportFactory::class, 'sendgrid' => SendgridTransportFactory::class, From c8c19b8ae841ee0a68d31190fe48d8fff9266b7d Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 23 Jul 2024 09:29:37 +0200 Subject: [PATCH 129/180] [FrameworkBundle] Deprecate `session.sid_length` and `session.sid_bits_per_character` config options --- CHANGELOG.md | 1 + DependencyInjection/Configuration.php | 2 ++ Tests/DependencyInjection/Fixtures/php/full.php | 2 -- Tests/DependencyInjection/Fixtures/xml/full.xml | 2 +- Tests/DependencyInjection/Fixtures/yml/full.yml | 2 -- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 2 -- 6 files changed, 4 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 193f4570c..4d7fbaa4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ CHANGELOG * Deprecate making `cache.app` adapter taggable, use the `cache.app.taggable` adapter instead * Enable `json_decode_detailed_errors` in the default serializer context in debug mode by default when `seld/jsonlint` is installed * Register `Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter` as a service named `serializer.name_converter.snake_case_to_camel_case` if available + * Deprecate `session.sid_length` and `session.sid_bits_per_character` config options 7.1 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 4e66371e4..02872f1b8 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -685,10 +685,12 @@ private function addSessionSection(ArrayNodeDefinition $rootNode): void ->integerNode('sid_length') ->min(22) ->max(256) + ->setDeprecated('symfony/framework-bundle', '7.2', 'Setting the "%path%.%node%" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option.') ->end() ->integerNode('sid_bits_per_character') ->min(4) ->max(6) + ->setDeprecated('symfony/framework-bundle', '7.2', 'Setting the "%path%.%node%" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option.') ->end() ->end() ->end() diff --git a/Tests/DependencyInjection/Fixtures/php/full.php b/Tests/DependencyInjection/Fixtures/php/full.php index 4fbf72a9f..8c97c84a5 100644 --- a/Tests/DependencyInjection/Fixtures/php/full.php +++ b/Tests/DependencyInjection/Fixtures/php/full.php @@ -43,8 +43,6 @@ 'gc_maxlifetime' => 90000, 'gc_divisor' => 108, 'gc_probability' => 1, - 'sid_length' => 22, - 'sid_bits_per_character' => 4, 'save_path' => '/path/to/sessions', ], 'assets' => [ diff --git a/Tests/DependencyInjection/Fixtures/xml/full.xml b/Tests/DependencyInjection/Fixtures/xml/full.xml index fd5d52e1c..48c5e6f6d 100644 --- a/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -17,7 +17,7 @@ - + text/csv diff --git a/Tests/DependencyInjection/Fixtures/yml/full.yml b/Tests/DependencyInjection/Fixtures/yml/full.yml index 96001f1d2..69a19baa4 100644 --- a/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -36,8 +36,6 @@ framework: gc_probability: 1 gc_divisor: 108 gc_maxlifetime: 90000 - sid_length: 22 - sid_bits_per_character: 4 save_path: /path/to/sessions assets: version: v1 diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index a6da61ae3..2fadb76fd 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -676,8 +676,6 @@ public function testSession() $this->assertEquals(108, $options['gc_divisor']); $this->assertEquals(1, $options['gc_probability']); $this->assertEquals(90000, $options['gc_maxlifetime']); - $this->assertEquals(22, $options['sid_length']); - $this->assertEquals(4, $options['sid_bits_per_character']); $this->assertEquals('/path/to/sessions', $container->getParameter('session.save_path')); } From 328ef309092b87b47b798a8464b8f91d2e6a0272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Ostroluck=C3=BD?= Date: Sat, 7 Sep 2024 23:01:09 +0200 Subject: [PATCH 130/180] [FrameworkBundle] Add --resolve-env-vars option to lint:container command --- CHANGELOG.md | 1 + Command/ContainerLintCommand.php | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 193f4570c..c60b730d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add support for setting `headers` with `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` + * Add `--resolve-env-vars` option to `lint:container` command * Derivate `kernel.secret` from the decryption secret when its env var is not defined * Make the `config/` directory optional in `MicroKernelTrait`, add support for service arguments in the invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing diff --git a/Command/ContainerLintCommand.php b/Command/ContainerLintCommand.php index 0e6c72d16..e794e88c4 100644 --- a/Command/ContainerLintCommand.php +++ b/Command/ContainerLintCommand.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Compiler\CheckAliasValidityPass; @@ -39,6 +40,7 @@ protected function configure(): void { $this ->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.') + ->addOption('resolve-env-vars', null, InputOption::VALUE_NONE, 'Resolve environment variables and fail if one is missing.') ; } @@ -58,7 +60,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $container->setParameter('container.build_time', time()); try { - $container->compile(); + $container->compile((bool) $input->getOption('resolve-env-vars')); } catch (InvalidArgumentException $e) { $errorIo->error($e->getMessage()); From b2f46bd80928cdf5942062697d68c0354acf308d Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 13 Sep 2024 02:53:00 +0200 Subject: [PATCH 131/180] [FrameworkBundle] Add ability to use existing service as lock/semaphore resource --- CHANGELOG.md | 1 + DependencyInjection/FrameworkExtension.php | 8 ++++- .../Fixtures/php/lock_service.php | 13 +++++++++ .../Fixtures/php/semaphore_service.php | 13 +++++++++ .../Fixtures/xml/lock_service.xml | 20 +++++++++++++ .../Fixtures/xml/semaphore_service.xml | 20 +++++++++++++ .../Fixtures/yml/lock_service.yml | 14 +++++++++ .../Fixtures/yml/semaphore_service.yml | 14 +++++++++ .../FrameworkExtensionTestCase.php | 29 +++++++++++++++++++ 9 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 Tests/DependencyInjection/Fixtures/php/lock_service.php create mode 100644 Tests/DependencyInjection/Fixtures/php/semaphore_service.php create mode 100644 Tests/DependencyInjection/Fixtures/xml/lock_service.xml create mode 100644 Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml create mode 100644 Tests/DependencyInjection/Fixtures/yml/lock_service.yml create mode 100644 Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index f5f05ff36..7b5bbaeda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ CHANGELOG * Enable `json_decode_detailed_errors` in the default serializer context in debug mode by default when `seld/jsonlint` is installed * Register `Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter` as a service named `serializer.name_converter.snake_case_to_camel_case` if available * Deprecate `session.sid_length` and `session.sid_bits_per_character` config options + * Add the ability to use an existing service as a lock/semaphore resource 7.1 --- diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 75cfe1d1f..5b644c740 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1230,7 +1230,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c } $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs); - if ($usedEnvs || preg_match('#^[a-z]++://#', $config['handler_id'])) { + if ($usedEnvs || str_contains($config['handler_id'], '://')) { $id = '.cache_connection.'.ContainerBuilder::hash($config['handler_id']); $container->getDefinition('session.abstract_handler') @@ -2004,6 +2004,9 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont $storeDefinitions = []; foreach ($resourceStores as $resourceStore) { $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); + if (!$usedEnvs && !str_contains($resourceStore, '://')) { + $resourceStore = new Reference($resourceStore); + } $storeDefinition = new Definition(PersistingStoreInterface::class); $storeDefinition ->setFactory([StoreFactory::class, 'createStore']) @@ -2045,6 +2048,9 @@ private function registerSemaphoreConfiguration(array $config, ContainerBuilder foreach ($config['resources'] as $resourceName => $resourceStore) { $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); + if (!$usedEnvs && !str_contains($resourceStore, '://')) { + $resourceStore = new Reference($resourceStore); + } $storeDefinition = new Definition(SemaphoreStoreInterface::class); $storeDefinition->setFactory([SemaphoreStoreFactory::class, 'createStore']); $storeDefinition->setArguments([$resourceStore]); diff --git a/Tests/DependencyInjection/Fixtures/php/lock_service.php b/Tests/DependencyInjection/Fixtures/php/lock_service.php new file mode 100644 index 000000000..b3a17ee43 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/php/lock_service.php @@ -0,0 +1,13 @@ +register('my_service', \Redis::class); +$container->setAlias('factory_public_alias', 'lock.default.factory') + ->setPublic(true); + +$container->loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'lock' => 'my_service', +]); diff --git a/Tests/DependencyInjection/Fixtures/php/semaphore_service.php b/Tests/DependencyInjection/Fixtures/php/semaphore_service.php new file mode 100644 index 000000000..e94d809be --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/php/semaphore_service.php @@ -0,0 +1,13 @@ +register('my_service', \Redis::class); +$container->setAlias('factory_public_alias', 'semaphore.default.factory') + ->setPublic(true); + +$container->loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'semaphore' => 'my_service', +]); diff --git a/Tests/DependencyInjection/Fixtures/xml/lock_service.xml b/Tests/DependencyInjection/Fixtures/xml/lock_service.xml new file mode 100644 index 000000000..d184cc2f7 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/xml/lock_service.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + my_service + + + diff --git a/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml b/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml new file mode 100644 index 000000000..4939a3300 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + my_service + + + diff --git a/Tests/DependencyInjection/Fixtures/yml/lock_service.yml b/Tests/DependencyInjection/Fixtures/yml/lock_service.yml new file mode 100644 index 000000000..4cea81ea0 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/yml/lock_service.yml @@ -0,0 +1,14 @@ +services: + my_service: + class: \Redis + factory_public_alias: + alias: lock.default.factory + public: true + +framework: + annotations: false + http_method_override: false + handle_all_throwables: true + php_errors: + log: true + lock: my_service diff --git a/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml b/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml new file mode 100644 index 000000000..f966965b5 --- /dev/null +++ b/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml @@ -0,0 +1,14 @@ +services: + my_service: + class: \Redis + factory_public_alias: + alias: semaphore.default.factory + public: true + +framework: + annotations: false + http_method_override: false + handle_all_throwables: true + php_errors: + log: true + semaphore: my_service diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index a381e1472..b4d7af104 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -34,6 +34,7 @@ use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -57,6 +58,7 @@ use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; +use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; @@ -67,6 +69,7 @@ use Symfony\Component\Notifier\TexterInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Security\Core\AuthenticationEvents; +use Symfony\Component\Semaphore\SemaphoreFactory; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; @@ -2433,6 +2436,19 @@ public function testNamedLocks() self::assertStringContainsString('REDIS_DSN', $storeDef->getArgument(0)); } + public function testLockWithService() + { + $container = $this->createContainerFromFile('lock_service', [], true, false); + $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveChildDefinitionsPass()]); + $container->compile(); + + self::assertTrue($container->hasDefinition('lock.default.factory')); + $storeDef = $container->getDefinition($container->getDefinition('lock.default.factory')->getArgument(0)); + self::assertEquals(new Reference('my_service'), $storeDef->getArgument(0)); + + self::assertInstanceOf(LockFactory::class, $container->get('factory_public_alias')); + } + public function testDefaultSemaphore() { $container = $this->createContainerFromFile('semaphore'); @@ -2455,6 +2471,19 @@ public function testNamedSemaphores() self::assertStringContainsString('REDIS_DSN', $storeDef->getArgument(0)); } + public function testSemaphoreWithService() + { + $container = $this->createContainerFromFile('semaphore_service', [], true, false); + $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveChildDefinitionsPass()]); + $container->compile(); + + self::assertTrue($container->hasDefinition('semaphore.default.factory')); + $storeDef = $container->getDefinition($container->getDefinition('semaphore.default.factory')->getArgument(0)); + self::assertEquals(new Reference('my_service'), $storeDef->getArgument(0)); + + self::assertInstanceOf(SemaphoreFactory::class, $container->get('factory_public_alias')); + } + protected function createContainer(array $data = []) { return new ContainerBuilder(new EnvPlaceholderParameterBag(array_merge([ From 63d2b98935adca0264ceef816ad33451e905915f Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Sun, 30 Jun 2024 23:54:38 -0400 Subject: [PATCH 132/180] Introducing container non-empty parameters --- DependencyInjection/FrameworkExtension.php | 1 + composer.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 75cfe1d1f..407ae5237 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -309,6 +309,7 @@ public function load(array $configs, ContainerBuilder $container): void if (isset($config['secret'])) { $container->setParameter('kernel.secret', $config['secret']); } + $container->nonEmptyParameter('kernel.secret', 'A non-empty value for the parameter "kernel.secret" is required. Did you forget to configure the "framework.secret" option?'); $container->setParameter('kernel.http_method_override', $config['http_method_override']); $container->setParameter('kernel.trust_x_sendfile_type_header', $config['trust_x_sendfile_type_header']); diff --git a/composer.json b/composer.json index e3e101e1a..da5b96454 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "ext-xml": "*", "symfony/cache": "^6.4|^7.0", "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^7.1.5", + "symfony/dependency-injection": "^7.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", "symfony/event-dispatcher": "^6.4|^7.0", From b3958d511c39b7ff646a9acc29cd280e317ae0e3 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Mon, 20 May 2024 06:59:56 +0200 Subject: [PATCH 133/180] [Serializer] Introduce named serializers --- CHANGELOG.md | 1 + DependencyInjection/Configuration.php | 43 +++++++++++++++--- DependencyInjection/FrameworkExtension.php | 3 ++ Resources/config/messenger.php | 2 +- Resources/config/schema/symfony-1.0.xsd | 11 +++++ Resources/config/serializer.php | 44 ++++++++++--------- Resources/config/serializer_debug.php | 1 + .../DependencyInjection/ConfigurationTest.php | 18 ++++++++ .../DependencyInjection/Fixtures/php/full.php | 7 +++ .../DependencyInjection/Fixtures/xml/full.xml | 5 +++ .../DependencyInjection/Fixtures/yml/full.yml | 6 +++ .../FrameworkExtensionTestCase.php | 20 +++++++++ 12 files changed, 133 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b5bbaeda..f6fb34737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ CHANGELOG * Register `Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter` as a service named `serializer.name_converter.snake_case_to_camel_case` if available * Deprecate `session.sid_length` and `session.sid_bits_per_character` config options * Add the ability to use an existing service as a lock/semaphore resource + * Add support for configuring multiple serializer instances via the configuration 7.1 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 02872f1b8..0914a0d22 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1099,10 +1099,22 @@ private function addAnnotationsSection(ArrayNodeDefinition $rootNode): void private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void { + $defaultContextNode = fn () => (new NodeBuilder()) + ->arrayNode('default_context') + ->normalizeKeys(false) + ->validate() + ->ifTrue(fn () => $this->debug && class_exists(JsonParser::class)) + ->then(fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) + ->end() + ->defaultValue([]) + ->prototype('variable')->end() + ; + $rootNode ->children() ->arrayNode('serializer') ->info('Serializer configuration') + ->fixXmlConfig('named_serializer', 'named_serializers') ->{$enableIfStandalone('symfony/serializer', Serializer::class)}() ->children() ->booleanNode('enable_attributes')->{class_exists(FullStack::class) ? 'defaultFalse' : 'defaultTrue'}()->end() @@ -1118,19 +1130,36 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $e ->end() ->end() ->end() - ->arrayNode('default_context') - ->normalizeKeys(false) + ->append($defaultContextNode()) + ->arrayNode('named_serializers') + ->useAttributeAsKey('name') + ->arrayPrototype() + ->children() + ->scalarNode('name_converter')->end() + ->append($defaultContextNode()) + ->booleanNode('include_built_in_normalizers') + ->info('Whether to include the built-in normalizers') + ->defaultTrue() + ->end() + ->booleanNode('include_built_in_encoders') + ->info('Whether to include the built-in encoders') + ->defaultTrue() + ->end() + ->end() + ->end() ->validate() - ->ifTrue(fn () => $this->debug && class_exists(JsonParser::class)) - ->then(fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) + ->ifTrue(fn ($v) => isset($v['default'])) + ->thenInvalid('"default" is a reserved name.') ->end() - ->defaultValue([]) - ->prototype('variable')->end() ->end() ->end() ->validate() ->ifTrue(fn ($v) => $this->debug && class_exists(JsonParser::class) && !isset($v['default_context'][JsonDecode::DETAILED_ERROR_MESSAGES])) - ->then(function ($v) { $v['default_context'][JsonDecode::DETAILED_ERROR_MESSAGES] = true; return $v; }) + ->then(function ($v) { + $v['default_context'][JsonDecode::DETAILED_ERROR_MESSAGES] = true; + + return $v; + }) ->end() ->end() ->end() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 44a27f903..17c779276 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1906,6 +1906,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); if (isset($config['name_converter']) && $config['name_converter']) { + $container->setParameter('.serializer.name_converter', $config['name_converter']); $container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter'])); } @@ -1934,6 +1935,8 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); $container->getDefinition('serializer.normalizer.property')->setArgument(5, $defaultContext); + + $container->setParameter('.serializer.named_serializers', $config['named_serializers'] ?? []); } private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void diff --git a/Resources/config/messenger.php b/Resources/config/messenger.php index df2476096..40f5b84ca 100644 --- a/Resources/config/messenger.php +++ b/Resources/config/messenger.php @@ -72,7 +72,7 @@ ]) ->set('serializer.normalizer.flatten_exception', FlattenExceptionNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -880]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -880]) ->set('messenger.transport.native_php_serializer', PhpSerializer::class) ->alias('messenger.default_serializer', 'messenger.transport.native_php_serializer') diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index c6816fbd0..64e9c76cb 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -320,6 +320,7 @@ + @@ -332,6 +333,16 @@ + + + + + + + + + + diff --git a/Resources/config/serializer.php b/Resources/config/serializer.php index 36c8b89b5..d689d4299 100644 --- a/Resources/config/serializer.php +++ b/Resources/config/serializer.php @@ -80,46 +80,46 @@ ->set('serializer.normalizer.constraint_violation_list', ConstraintViolationListNormalizer::class) ->args([1 => service('serializer.name_converter.metadata_aware')]) ->autowire(true) - ->tag('serializer.normalizer', ['priority' => -915]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -915]) ->set('serializer.normalizer.mime_message', MimeMessageNormalizer::class) ->args([service('serializer.normalizer.property')]) - ->tag('serializer.normalizer', ['priority' => -915]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -915]) ->set('serializer.normalizer.datetimezone', DateTimeZoneNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -915]) ->set('serializer.normalizer.dateinterval', DateIntervalNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -915]) ->set('serializer.normalizer.data_uri', DataUriNormalizer::class) ->args([service('mime_types')->nullOnInvalid()]) - ->tag('serializer.normalizer', ['priority' => -920]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -920]) ->set('serializer.normalizer.datetime', DateTimeNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -910]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -910]) ->set('serializer.normalizer.json_serializable', JsonSerializableNormalizer::class) ->args([null, null]) - ->tag('serializer.normalizer', ['priority' => -950]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -950]) ->set('serializer.normalizer.problem', ProblemNormalizer::class) ->args([param('kernel.debug'), '$translator' => service('translator')->nullOnInvalid()]) - ->tag('serializer.normalizer', ['priority' => -890]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -890]) ->set('serializer.denormalizer.unwrapping', UnwrappingDenormalizer::class) ->args([service('serializer.property_accessor')]) - ->tag('serializer.normalizer', ['priority' => 1000]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => 1000]) ->set('serializer.normalizer.uid', UidNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -890]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -890]) ->set('serializer.normalizer.translatable', TranslatableNormalizer::class) ->args(['$translator' => service('translator')]) - ->tag('serializer.normalizer', ['priority' => -920]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -920]) ->set('serializer.normalizer.form_error', FormErrorNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -915]) ->set('serializer.normalizer.object', ObjectNormalizer::class) ->args([ @@ -132,7 +132,7 @@ null, service('property_info')->ignoreOnInvalid(), ]) - ->tag('serializer.normalizer', ['priority' => -1000]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -1000]) ->set('serializer.normalizer.property', PropertyNormalizer::class) ->args([ @@ -144,7 +144,7 @@ ]) ->set('serializer.denormalizer.array', ArrayDenormalizer::class) - ->tag('serializer.normalizer', ['priority' => -990]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -990]) // Loader ->set('serializer.mapping.chain_loader', LoaderChain::class) @@ -174,26 +174,30 @@ // Encoders ->set('serializer.encoder.xml', XmlEncoder::class) - ->tag('serializer.encoder') + ->tag('serializer.encoder', ['built_in' => true]) ->set('serializer.encoder.json', JsonEncoder::class) ->args([null, null]) - ->tag('serializer.encoder') + ->tag('serializer.encoder', ['built_in' => true]) ->set('serializer.encoder.yaml', YamlEncoder::class) ->args([null, null]) - ->tag('serializer.encoder') + ->tag('serializer.encoder', ['built_in' => true]) ->set('serializer.encoder.csv', CsvEncoder::class) - ->tag('serializer.encoder') + ->tag('serializer.encoder', ['built_in' => true]) // Name converters ->set('serializer.name_converter.camel_case_to_snake_case', CamelCaseToSnakeCaseNameConverter::class) ->set('serializer.name_converter.snake_case_to_camel_case', SnakeCaseToCamelCaseNameConverter::class) - ->set('serializer.name_converter.metadata_aware', MetadataAwareNameConverter::class) + ->set('serializer.name_converter.metadata_aware.abstract', MetadataAwareNameConverter::class) + ->abstract() ->args([service('serializer.mapping.class_metadata_factory')]) + ->set('serializer.name_converter.metadata_aware') + ->parent('serializer.name_converter.metadata_aware.abstract') + // PropertyInfo extractor ->set('property_info.serializer_extractor', SerializerExtractor::class) ->args([service('serializer.mapping.class_metadata_factory')]) @@ -216,6 +220,6 @@ ]) ->set('serializer.normalizer.backed_enum', BackedEnumNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) + ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -915]) ; }; diff --git a/Resources/config/serializer_debug.php b/Resources/config/serializer_debug.php index 45b764fdd..520d145cb 100644 --- a/Resources/config/serializer_debug.php +++ b/Resources/config/serializer_debug.php @@ -21,6 +21,7 @@ ->args([ service('debug.serializer.inner'), service('serializer.data_collector'), + 'default', ]) ->set('serializer.data_collector', SerializerDataCollector::class) diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index c4c81538c..73e6c2025 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -784,6 +784,7 @@ protected static function getBundleDefaultConfig() 'enabled' => true, 'enable_attributes' => !class_exists(FullStack::class), 'mapping' => ['paths' => []], + 'named_serializers' => [], ], 'property_access' => [ 'enabled' => true, @@ -958,4 +959,21 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], ]; } + + public function testNamedSerializersReservedName() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('Invalid configuration for path "framework.serializer.named_serializers": "default" is a reserved name.'); + + $processor->processConfiguration($configuration, [[ + 'serializer' => [ + 'named_serializers' => [ + 'default' => ['include_built_in_normalizers' => false], + ], + ], + ]]); + } } diff --git a/Tests/DependencyInjection/Fixtures/php/full.php b/Tests/DependencyInjection/Fixtures/php/full.php index 8c97c84a5..0a32ce8b3 100644 --- a/Tests/DependencyInjection/Fixtures/php/full.php +++ b/Tests/DependencyInjection/Fixtures/php/full.php @@ -66,6 +66,13 @@ 'circular_reference_handler' => 'my.circular.reference.handler', 'max_depth_handler' => 'my.max.depth.handler', 'default_context' => ['enable_max_depth' => true], + 'named_serializers' => [ + 'api' => [ + 'include_built_in_normalizers' => true, + 'include_built_in_encoders' => true, + 'default_context' => ['enable_max_depth' => false], + ], + ], ], 'property_info' => true, 'type_info' => true, diff --git a/Tests/DependencyInjection/Fixtures/xml/full.xml b/Tests/DependencyInjection/Fixtures/xml/full.xml index 48c5e6f6d..c01e85783 100644 --- a/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -38,6 +38,11 @@ true + + + false + + diff --git a/Tests/DependencyInjection/Fixtures/yml/full.yml b/Tests/DependencyInjection/Fixtures/yml/full.yml index 69a19baa4..7550749eb 100644 --- a/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -57,6 +57,12 @@ framework: max_depth_handler: my.max.depth.handler default_context: enable_max_depth: true + named_serializers: + api: + include_built_in_normalizers: true + include_built_in_encoders: true + default_context: + enable_max_depth: false type_info: ~ property_info: ~ ide: file%%link%%format diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index b4d7af104..8d902bd47 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1463,6 +1463,26 @@ public function testSerializerWithoutTranslator() $this->assertFalse($container->hasDefinition('serializer.normalizer.translatable')); } + public function testSerializerDefaultParameters() + { + $container = $this->createContainerFromFile('serializer_enabled'); + $this->assertFalse($container->hasParameter('.serializer.name_converter')); + $this->assertFalse($container->hasParameter('serializer.default_context')); + $this->assertTrue($container->hasParameter('.serializer.named_serializers')); + $this->assertSame([], $container->getParameter('.serializer.named_serializers')); + } + + public function testSerializerParametersAreSet() + { + $container = $this->createContainerFromFile('full'); + $this->assertTrue($container->hasParameter('.serializer.name_converter')); + $this->assertSame('serializer.name_converter.camel_case_to_snake_case', $container->getParameter('.serializer.name_converter')); + $this->assertTrue($container->hasParameter('serializer.default_context')); + $this->assertSame(['enable_max_depth' => true], $container->getParameter('serializer.default_context')); + $this->assertTrue($container->hasParameter('.serializer.named_serializers')); + $this->assertSame(['api' => ['include_built_in_normalizers' => true, 'include_built_in_encoders' => true, 'default_context' => ['enable_max_depth' => false]]], $container->getParameter('.serializer.named_serializers')); + } + public function testRegisterSerializerExtractor() { $container = $this->createContainerFromFile('full'); From eda025df6deb419d73fc478c4c892cc66ed25434 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 19 Sep 2024 09:56:35 +0200 Subject: [PATCH 134/180] Switch to ExpectUserDeprecationMessageTrait --- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 8d902bd47..5f8562e67 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -13,7 +13,7 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; @@ -98,7 +98,7 @@ abstract class FrameworkExtensionTestCase extends TestCase { - use ExpectDeprecationTrait; + use ExpectUserDeprecationMessageTrait; private static array $containerCache = []; @@ -1863,7 +1863,7 @@ public function testCacheTaggableTagAppliedToPools() */ public function testTaggableCacheAppIsDeprecated() { - $this->expectDeprecation('Since symfony/framework-bundle 7.2: Using the "tags" option with the "cache.app" adapter is deprecated. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); + $this->expectUserDeprecationMessage('Since symfony/framework-bundle 7.2: Using the "tags" option with the "cache.app" adapter is deprecated. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); $this->createContainerFromFile('cache_cacheapp_tagaware'); } From 80325b96ae8cff6def34ef0adffabf6809864288 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 21 Sep 2024 09:18:43 +0200 Subject: [PATCH 135/180] fix tests to not depend on the installation of the redis extension --- Tests/DependencyInjection/Fixtures/php/lock_service.php | 2 -- .../DependencyInjection/Fixtures/php/semaphore_service.php | 2 -- Tests/DependencyInjection/Fixtures/xml/lock_service.xml | 1 - .../DependencyInjection/Fixtures/xml/semaphore_service.xml | 1 - Tests/DependencyInjection/Fixtures/yml/lock_service.yml | 3 --- .../DependencyInjection/Fixtures/yml/semaphore_service.yml | 3 --- Tests/DependencyInjection/FrameworkExtensionTestCase.php | 6 ------ 7 files changed, 18 deletions(-) diff --git a/Tests/DependencyInjection/Fixtures/php/lock_service.php b/Tests/DependencyInjection/Fixtures/php/lock_service.php index b3a17ee43..4bdbd29b8 100644 --- a/Tests/DependencyInjection/Fixtures/php/lock_service.php +++ b/Tests/DependencyInjection/Fixtures/php/lock_service.php @@ -1,8 +1,6 @@ register('my_service', \Redis::class); -$container->setAlias('factory_public_alias', 'lock.default.factory') - ->setPublic(true); $container->loadFromExtension('framework', [ 'annotations' => false, diff --git a/Tests/DependencyInjection/Fixtures/php/semaphore_service.php b/Tests/DependencyInjection/Fixtures/php/semaphore_service.php index e94d809be..279f1c158 100644 --- a/Tests/DependencyInjection/Fixtures/php/semaphore_service.php +++ b/Tests/DependencyInjection/Fixtures/php/semaphore_service.php @@ -1,8 +1,6 @@ register('my_service', \Redis::class); -$container->setAlias('factory_public_alias', 'semaphore.default.factory') - ->setPublic(true); $container->loadFromExtension('framework', [ 'annotations' => false, diff --git a/Tests/DependencyInjection/Fixtures/xml/lock_service.xml b/Tests/DependencyInjection/Fixtures/xml/lock_service.xml index d184cc2f7..a175526a9 100644 --- a/Tests/DependencyInjection/Fixtures/xml/lock_service.xml +++ b/Tests/DependencyInjection/Fixtures/xml/lock_service.xml @@ -7,7 +7,6 @@ - diff --git a/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml b/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml index 4939a3300..814823802 100644 --- a/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml +++ b/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml @@ -7,7 +7,6 @@ - diff --git a/Tests/DependencyInjection/Fixtures/yml/lock_service.yml b/Tests/DependencyInjection/Fixtures/yml/lock_service.yml index 4cea81ea0..1b5dfea17 100644 --- a/Tests/DependencyInjection/Fixtures/yml/lock_service.yml +++ b/Tests/DependencyInjection/Fixtures/yml/lock_service.yml @@ -1,9 +1,6 @@ services: my_service: class: \Redis - factory_public_alias: - alias: lock.default.factory - public: true framework: annotations: false diff --git a/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml b/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml index f966965b5..62765ac91 100644 --- a/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml +++ b/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml @@ -1,9 +1,6 @@ services: my_service: class: \Redis - factory_public_alias: - alias: semaphore.default.factory - public: true framework: annotations: false diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 5f8562e67..fc66c889f 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -58,7 +58,6 @@ use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; -use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; @@ -69,7 +68,6 @@ use Symfony\Component\Notifier\TexterInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Security\Core\AuthenticationEvents; -use Symfony\Component\Semaphore\SemaphoreFactory; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; @@ -2465,8 +2463,6 @@ public function testLockWithService() self::assertTrue($container->hasDefinition('lock.default.factory')); $storeDef = $container->getDefinition($container->getDefinition('lock.default.factory')->getArgument(0)); self::assertEquals(new Reference('my_service'), $storeDef->getArgument(0)); - - self::assertInstanceOf(LockFactory::class, $container->get('factory_public_alias')); } public function testDefaultSemaphore() @@ -2500,8 +2496,6 @@ public function testSemaphoreWithService() self::assertTrue($container->hasDefinition('semaphore.default.factory')); $storeDef = $container->getDefinition($container->getDefinition('semaphore.default.factory')->getArgument(0)); self::assertEquals(new Reference('my_service'), $storeDef->getArgument(0)); - - self::assertInstanceOf(SemaphoreFactory::class, $container->get('factory_public_alias')); } protected function createContainer(array $data = []) From 777484373ee96258184a6ece27050a8341452054 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Mon, 23 Sep 2024 09:07:01 -0400 Subject: [PATCH 136/180] rename non-empty parameter methods --- DependencyInjection/FrameworkExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 17c779276..e4e32affe 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -309,7 +309,7 @@ public function load(array $configs, ContainerBuilder $container): void if (isset($config['secret'])) { $container->setParameter('kernel.secret', $config['secret']); } - $container->nonEmptyParameter('kernel.secret', 'A non-empty value for the parameter "kernel.secret" is required. Did you forget to configure the "framework.secret" option?'); + $container->parameterCannotBeEmpty('kernel.secret', 'A non-empty value for the parameter "kernel.secret" is required. Did you forget to configure the "framework.secret" option?'); $container->setParameter('kernel.http_method_override', $config['http_method_override']); $container->setParameter('kernel.trust_x_sendfile_type_header', $config['trust_x_sendfile_type_header']); From a5fc026a01fb5b91617908cff759bf37ec352c46 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 24 Sep 2024 13:28:07 +0200 Subject: [PATCH 137/180] Remove useless parent method calls in tests --- Tests/Functional/UidTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tests/Functional/UidTest.php b/Tests/Functional/UidTest.php index da0b1e4fc..245cb11b6 100644 --- a/Tests/Functional/UidTest.php +++ b/Tests/Functional/UidTest.php @@ -20,8 +20,6 @@ class UidTest extends AbstractWebTestCase { protected function setUp(): void { - parent::setUp(); - self::deleteTmpDir(); } From ffe8193ad33c98477462a7478544cc0dad1f8b8b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Sep 2024 14:33:41 +0200 Subject: [PATCH 138/180] [FrameworkBundle][HttpKernel] Add support for `SYMFONY_TRUSTED_PROXIES`, `SYMFONY_TRUSTED_HEADERS`, `SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER` and `SYMFONY_TRUSTED_HOSTS` env vars --- CHANGELOG.md | 1 + DependencyInjection/Configuration.php | 17 ++++++------- DependencyInjection/FrameworkExtension.php | 25 +++---------------- .../DependencyInjection/ConfigurationTest.php | 11 +++----- 4 files changed, 15 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6fb34737..e9a7186a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ CHANGELOG * Deprecate `session.sid_length` and `session.sid_bits_per_character` config options * Add the ability to use an existing service as a lock/semaphore resource * Add support for configuring multiple serializer instances via the configuration + * Add support for `SYMFONY_TRUSTED_PROXIES`, `SYMFONY_TRUSTED_HEADERS`, `SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER` and `SYMFONY_TRUSTED_HOSTS` env vars 7.1 --- diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 0914a0d22..aeb36ca5f 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -90,7 +90,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->scalarNode('trust_x_sendfile_type_header') ->info('Set true to enable support for xsendfile in binary file responses.') - ->defaultFalse() + ->defaultValue('%env(bool:default::SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER)%') ->end() ->scalarNode('ide')->defaultValue($this->debug ? '%env(default::SYMFONY_IDE)%' : null)->end() ->booleanNode('test')->end() @@ -108,26 +108,23 @@ 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 ? [$v] : [])->end() ->prototype('scalar')->end() + ->defaultValue(['%env(default::SYMFONY_TRUSTED_HOSTS)%']) ->end() ->variableNode('trusted_proxies') ->beforeNormalization() ->ifTrue(fn ($v) => 'private_ranges' === $v || 'PRIVATE_SUBNETS' === $v) ->then(fn () => IpUtils::PRIVATE_SUBNETS) ->end() + ->defaultValue(['%env(default::SYMFONY_TRUSTED_PROXIES)%']) ->end() ->arrayNode('trusted_headers') ->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() - ->enumPrototype() - ->values([ - 'forwarded', - 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix', - ]) - ->end() + ->beforeNormalization()->ifString()->then(static fn ($v) => $v ? [$v] : [])->end() + ->prototype('scalar')->end() + ->defaultValue(['%env(default::SYMFONY_TRUSTED_HEADERS)%']) ->end() ->scalarNode('error_controller') ->defaultValue('error_controller') diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 17c779276..8011c964f 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -313,14 +313,14 @@ public function load(array $configs, ContainerBuilder $container): void $container->setParameter('kernel.http_method_override', $config['http_method_override']); $container->setParameter('kernel.trust_x_sendfile_type_header', $config['trust_x_sendfile_type_header']); - $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); + $container->setParameter('kernel.trusted_hosts', [0] === array_keys($config['trusted_hosts']) ? $config['trusted_hosts'][0] : $config['trusted_hosts']); $container->setParameter('kernel.default_locale', $config['default_locale']); $container->setParameter('kernel.enabled_locales', $config['enabled_locales']); $container->setParameter('kernel.error_controller', $config['error_controller']); if (($config['trusted_proxies'] ?? false) && ($config['trusted_headers'] ?? false)) { - $container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']); - $container->setParameter('kernel.trusted_headers', $this->resolveTrustedHeaders($config['trusted_headers'])); + $container->setParameter('kernel.trusted_proxies', \is_array($config['trusted_proxies']) && [0] === array_keys($config['trusted_proxies']) ? $config['trusted_proxies'][0] : $config['trusted_proxies']); + $container->setParameter('kernel.trusted_headers', [0] === array_keys($config['trusted_headers']) ? $config['trusted_headers'][0] : $config['trusted_headers']); } if (!$container->hasParameter('debug.file_link_format')) { @@ -3114,25 +3114,6 @@ private function registerHtmlSanitizerConfiguration(array $config, ContainerBuil } } - private function resolveTrustedHeaders(array $headers): int - { - $trustedHeaders = 0; - - foreach ($headers as $h) { - $trustedHeaders |= match ($h) { - 'forwarded' => Request::HEADER_FORWARDED, - 'x-forwarded-for' => Request::HEADER_X_FORWARDED_FOR, - 'x-forwarded-host' => Request::HEADER_X_FORWARDED_HOST, - 'x-forwarded-proto' => Request::HEADER_X_FORWARDED_PROTO, - 'x-forwarded-port' => Request::HEADER_X_FORWARDED_PORT, - 'x-forwarded-prefix' => Request::HEADER_X_FORWARDED_PREFIX, - default => 0, - }; - } - - return $trustedHeaders; - } - public function getXsdValidationBasePath(): string|false { return \dirname(__DIR__).'/Resources/config/schema'; diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 73e6c2025..c569a852d 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -704,19 +704,16 @@ protected static function getBundleDefaultConfig() return [ 'http_method_override' => false, 'handle_all_throwables' => true, - 'trust_x_sendfile_type_header' => false, + 'trust_x_sendfile_type_header' => '%env(bool:default::SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER)%', 'ide' => '%env(default::SYMFONY_IDE)%', 'default_locale' => 'en', 'enabled_locales' => [], 'set_locale_from_accept_language' => false, 'set_content_language_from_locale' => false, 'secret' => 's3cr3t', - 'trusted_hosts' => [], - 'trusted_headers' => [ - 'x-forwarded-for', - 'x-forwarded-port', - 'x-forwarded-proto', - ], + 'trusted_hosts' => ['%env(default::SYMFONY_TRUSTED_HOSTS)%'], + 'trusted_proxies' => ['%env(default::SYMFONY_TRUSTED_PROXIES)%'], + 'trusted_headers' => ['%env(default::SYMFONY_TRUSTED_HEADERS)%'], 'csrf_protection' => [ 'enabled' => false, ], From 919bc2e0c7dc573b29af66fd8bfebda938a17c00 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 25 Sep 2024 22:02:16 +0200 Subject: [PATCH 139/180] fix named parameters in data providers --- Tests/Functional/ApiAttributesTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Functional/ApiAttributesTest.php b/Tests/Functional/ApiAttributesTest.php index a64da93b3..350446dc7 100644 --- a/Tests/Functional/ApiAttributesTest.php +++ b/Tests/Functional/ApiAttributesTest.php @@ -705,7 +705,7 @@ public static function mapRequestPayloadProvider(): iterable yield 'invalid request mapping attribute with default value' => [ 'uri' => '/map-request-to-attribute-with-default-value.json', 'format' => 'json', - 'input' => ['comment' => '', 'approved' => '1'], + 'parameters' => ['comment' => '', 'approved' => '1'], 'content' => null, 'expectedResponse' => <<<'JSON' { @@ -964,7 +964,7 @@ public static function mapRequestPayloadProvider(): iterable yield 'invalid request mapping non-nullable attribute without default value' => [ 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', 'format' => 'json', - 'input' => ['comment' => '', 'approved' => '1'], + 'parameters' => ['comment' => '', 'approved' => '1'], 'content' => null, 'expectedResponse' => <<<'JSON' { From f7f6aae026a9e144c09bf45da3bee86ab4c88293 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 26 Sep 2024 10:09:09 +0200 Subject: [PATCH 140/180] Remove unused imports --- Tests/DependencyInjection/Fixtures/php/notifier.php | 3 --- .../Fixtures/php/notifier_without_mailer.php | 3 --- .../Fixtures/php/notifier_without_messenger.php | 3 --- .../Fixtures/php/notifier_without_transports.php | 3 --- 4 files changed, 12 deletions(-) diff --git a/Tests/DependencyInjection/Fixtures/php/notifier.php b/Tests/DependencyInjection/Fixtures/php/notifier.php index 9abf2c880..058ec7175 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier.php @@ -1,8 +1,5 @@ loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php b/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php index fbb988527..107803ef9 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php @@ -1,8 +1,5 @@ loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php b/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php index 454f8ccec..0c43db7cd 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php @@ -1,8 +1,5 @@ loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, diff --git a/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php b/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php index 5861634e1..6392f0b33 100644 --- a/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php +++ b/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php @@ -1,8 +1,5 @@ loadFromExtension('framework', [ 'annotations' => false, 'http_method_override' => false, From 43c85605ce1452507ea09e25d1ffa0c3c281f813 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Sat, 14 Sep 2024 17:20:04 -0400 Subject: [PATCH 141/180] [Mailer] add Mailtrap webhook support --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/mailer_webhook.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 200310ec9..83bb23f2b 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2681,6 +2681,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co 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', diff --git a/Resources/config/mailer_webhook.php b/Resources/config/mailer_webhook.php index f0a50800f..e6f6c425b 100644 --- a/Resources/config/mailer_webhook.php +++ b/Resources/config/mailer_webhook.php @@ -21,6 +21,8 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Webhook\MailjetRequestParser; use Symfony\Component\Mailer\Bridge\Mailomat\RemoteEvent\MailomatPayloadConverter; use Symfony\Component\Mailer\Bridge\Mailomat\Webhook\MailomatRequestParser; +use Symfony\Component\Mailer\Bridge\Mailtrap\RemoteEvent\MailtrapPayloadConverter; +use Symfony\Component\Mailer\Bridge\Mailtrap\Webhook\MailtrapRequestParser; use Symfony\Component\Mailer\Bridge\Postmark\RemoteEvent\PostmarkPayloadConverter; use Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser; use Symfony\Component\Mailer\Bridge\Resend\RemoteEvent\ResendPayloadConverter; @@ -62,6 +64,11 @@ ->args([service('mailer.payload_converter.postmark')]) ->alias(PostmarkRequestParser::class, 'mailer.webhook.request_parser.postmark') + ->set('mailer.payload_converter.mailtrap', MailtrapPayloadConverter::class) + ->set('mailer.webhook.request_parser.mailtrap', MailtrapRequestParser::class) + ->args([service('mailer.payload_converter.mailtrap')]) + ->alias(MailtrapRequestParser::class, 'mailer.webhook.request_parser.mailtrap') + ->set('mailer.payload_converter.resend', ResendPayloadConverter::class) ->set('mailer.webhook.request_parser.resend', ResendRequestParser::class) ->args([service('mailer.payload_converter.resend')]) From 585504cc56b3a3586ea56106e8048f865c5b4507 Mon Sep 17 00:00:00 2001 From: Daniel Gorgan Date: Fri, 27 Sep 2024 19:27:01 +0300 Subject: [PATCH 142/180] Fix git --- CHANGELOG.md | 1 + Command/TranslationUpdateCommand.php | 85 +++++++++++++++---- .../Command/TranslationUpdateCommandTest.php | 29 ++++++- 3 files changed, 97 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9a7186a4..19ce70b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.2 --- + * Add support for `--sort` option when extracting translations with `translation:extract` command and `--force` option * Add support for setting `headers` with `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` * Add `--resolve-env-vars` option to `lint:container` command * Derivate `kernel.secret` from the decryption secret when its env var is not defined diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index 2f61c81d6..04f812146 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -76,7 +76,7 @@ protected function configure(): void new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to extract'), - new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically (only works with --dump-messages)', 'asc'), + new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically'), new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setHelp(<<<'EOF' @@ -100,7 +100,7 @@ protected function configure(): void 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% --force --sort=desc fr You can dump a tree-like structure using the yaml format with --as-tree flag: @@ -207,6 +207,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int $operation->moveMessagesToIntlDomainsIfPossible('new'); + if ($sort = $input->getOption('sort')) { + $sort = strtolower($sort); + if (!\in_array($sort, self::SORT_ORDERS, true)) { + $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); + + return 1; + } + } + // show compiled list of messages if (true === $input->getOption('dump-messages')) { $extractedMessagesCount = 0; @@ -223,19 +232,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $domainMessagesCount = \count($list); - if ($sort = $input->getOption('sort')) { - $sort = strtolower($sort); - if (!\in_array($sort, self::SORT_ORDERS, true)) { - $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); - - return 1; - } - - if (self::DESC === $sort) { - rsort($list); - } else { - sort($list); - } + if (self::DESC === $sort) { + rsort($list); + } else { + sort($list); } $io->section(\sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); @@ -266,7 +266,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int $bundleTransPath = end($transPaths); } - $this->writer->write($operation->getResult(), $format, ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $xliffVersion, 'as_tree' => $input->getOption('as-tree'), 'inline' => $input->getOption('as-tree') ?? 0]); + $operationResult = $operation->getResult(); + if ($sort) { + $operationResult = $this->sortCatalogue($operationResult, $sort); + } + + $this->writer->write($operationResult, $format, ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $xliffVersion, 'as_tree' => $input->getOption('as-tree'), 'inline' => $input->getOption('as-tree') ?? 0]); if (true === $input->getOption('dump-messages')) { $resultMessage .= ' and translation files were updated'; @@ -365,6 +370,54 @@ private function filterCatalogue(MessageCatalogue $catalogue, string $domain): M return $filteredCatalogue; } + private function sortCatalogue(MessageCatalogue $catalogue, string $sort): MessageCatalogue + { + $sortedCatalogue = new MessageCatalogue($catalogue->getLocale()); + + foreach ($catalogue->getDomains() as $domain) { + // extract intl-icu messages only + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + if ($intlMessages = $catalogue->all($intlDomain)) { + if (self::DESC === $sort) { + krsort($intlMessages); + } elseif (self::ASC === $sort) { + ksort($intlMessages); + } + + $sortedCatalogue->add($intlMessages, $intlDomain); + } + + // extract all messages and subtract intl-icu messages + if ($messages = array_diff($catalogue->all($domain), $intlMessages)) { + if (self::DESC === $sort) { + krsort($messages); + } elseif (self::ASC === $sort) { + ksort($messages); + } + + $sortedCatalogue->add($messages, $domain); + } + + if ($metadata = $catalogue->getMetadata('', $intlDomain)) { + foreach ($metadata as $k => $v) { + $sortedCatalogue->setMetadata($k, $v, $intlDomain); + } + } + + if ($metadata = $catalogue->getMetadata('', $domain)) { + foreach ($metadata as $k => $v) { + $sortedCatalogue->setMetadata($k, $v, $domain); + } + } + } + + foreach ($catalogue->getResources() as $resource) { + $sortedCatalogue->addResource($resource); + } + + return $sortedCatalogue; + } + private function extractMessages(string $locale, array $transPaths, string $prefix): MessageCatalogue { $extractedCatalogue = new MessageCatalogue($locale); diff --git a/Tests/Command/TranslationUpdateCommandTest.php b/Tests/Command/TranslationUpdateCommandTest.php index def589f58..2304e75ad 100644 --- a/Tests/Command/TranslationUpdateCommandTest.php +++ b/Tests/Command/TranslationUpdateCommandTest.php @@ -20,6 +20,7 @@ use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Translation\Extractor\ExtractorInterface; +use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Reader\TranslationReader; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\Writer\TranslationWriter; @@ -103,11 +104,25 @@ public function testDumpMessagesForSpecificDomain() public function testWriteMessages() { - $tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]); + $tester = $this->createCommandTester(['messages' => ['foo' => 'foo', 'test' => 'test', 'bar' => 'bar']], writerMessages: ['foo', 'test', 'bar']); $tester->execute(['command' => 'translation:extract', 'locale' => 'en', 'bundle' => 'foo', '--force' => true]); $this->assertMatchesRegularExpression('/Translation files were successfully updated./', $tester->getDisplay()); } + public function testWriteSortMessages() + { + $tester = $this->createCommandTester(['messages' => ['foo' => 'foo', 'test' => 'test', 'bar' => 'bar']], writerMessages: ['bar', 'foo', 'test']); + $tester->execute(['command' => 'translation:extract', 'locale' => 'en', 'bundle' => 'foo', '--force' => true, '--sort' => 'asc']); + $this->assertMatchesRegularExpression('/Translation files were successfully updated./', $tester->getDisplay()); + } + + public function testWriteReverseSortedMessages() + { + $tester = $this->createCommandTester(['messages' => ['foo' => 'foo', 'test' => 'test', 'bar' => 'bar']], writerMessages: ['test', 'foo', 'bar']); + $tester->execute(['command' => 'translation:extract', 'locale' => 'en', 'bundle' => 'foo', '--force' => true, '--sort' => 'desc']); + $this->assertMatchesRegularExpression('/Translation files were successfully updated./', $tester->getDisplay()); + } + public function testWriteMessagesInRootDirectory() { $tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]); @@ -175,7 +190,7 @@ protected function tearDown(): void $this->fs->remove($this->translationDir); } - private function createCommandTester($extractedMessages = [], $loadedMessages = [], ?KernelInterface $kernel = null, array $transPaths = [], array $codePaths = []): CommandTester + private function createCommandTester($extractedMessages = [], $loadedMessages = [], ?KernelInterface $kernel = null, array $transPaths = [], array $codePaths = [], ?array $writerMessages = null): CommandTester { $translator = $this->createMock(Translator::class); $translator @@ -212,6 +227,16 @@ function ($path, $catalogue) use ($loadedMessages) { ->willReturn( ['xlf', 'yml', 'yaml'] ); + if (null !== $writerMessages) { + $writer + ->expects($this->any()) + ->method('write') + ->willReturnCallback( + function (MessageCatalogue $catalogue) use ($writerMessages) { + $this->assertSame($writerMessages, array_keys($catalogue->all()['messages'])); + } + ); + } if (null === $kernel) { $returnValues = [ From 68ece90b3478d75523d162146a67081bf4852549 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 30 Sep 2024 15:26:46 +0200 Subject: [PATCH 143/180] [FrameworkBundle] Never hash the empty decryption key to compute kernel.secret --- Secrets/SodiumVault.php | 6 +++--- Tests/Secrets/SodiumVaultTest.php | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Secrets/SodiumVault.php b/Secrets/SodiumVault.php index f747fed14..2a8e5dcc8 100644 --- a/Secrets/SodiumVault.php +++ b/Secrets/SodiumVault.php @@ -114,7 +114,7 @@ public function reveal(string $name): ?string $this->loadKeys(); - if ('' === $this->decryptionKey) { + if ('' === $this->decryptionKey = (string) $this->decryptionKey) { $this->lastMessage = \sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); return null; @@ -181,8 +181,8 @@ public function loadEnvVars(): array } if ($this->derivedSecretEnvVar && !\array_key_exists($this->derivedSecretEnvVar, $envs)) { - $decryptionKey = $this->decryptionKey; - $envs[$this->derivedSecretEnvVar] = LazyString::fromCallable(static fn () => base64_encode(hash('sha256', $decryptionKey, true))); + $k = $this->decryptionKey; + $envs[$this->derivedSecretEnvVar] = LazyString::fromCallable(static fn () => '' !== ($k = (string) $k) ? base64_encode(hash('sha256', $k, true)) : ''); } return $envs; diff --git a/Tests/Secrets/SodiumVaultTest.php b/Tests/Secrets/SodiumVaultTest.php index e31e8364f..f91f4bced 100644 --- a/Tests/Secrets/SodiumVaultTest.php +++ b/Tests/Secrets/SodiumVaultTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\String\LazyString; /** * @requires extension sodium @@ -84,4 +85,17 @@ public function testDerivedSecretEnvVar() $this->assertSame(['FOO', 'MY_SECRET'], array_keys($vault->loadEnvVars())); } + + public function testEmptySecretEnvVar() + { + $vault = new SodiumVault($this->secretsDir, '', 'MY_SECRET'); + $envVars = $vault->loadEnvVars(); + $envVars['MY_SECRET'] = (string) $envVars['MY_SECRET']; + $this->assertSame(['MY_SECRET' => ''], $envVars); + + $vault = new SodiumVault($this->secretsDir, LazyString::fromCallable(fn () => ''), 'MY_SECRET'); + $envVars = $vault->loadEnvVars(); + $envVars['MY_SECRET'] = (string) $envVars['MY_SECRET']; + $this->assertSame(['MY_SECRET' => ''], $envVars); + } } From 7e09e75c5fcdc8bbf769303557b54f1c3be34960 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 2 Oct 2024 10:47:28 +0200 Subject: [PATCH 144/180] Make `@var` occurrences consistent --- Tests/Functional/Bundle/TestBundle/TestBundle.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/Bundle/TestBundle/TestBundle.php b/Tests/Functional/Bundle/TestBundle/TestBundle.php index d0c6588b0..73cb63d1f 100644 --- a/Tests/Functional/Bundle/TestBundle/TestBundle.php +++ b/Tests/Functional/Bundle/TestBundle/TestBundle.php @@ -24,7 +24,7 @@ public function build(ContainerBuilder $container): void { parent::build($container); - /** @var $extension DependencyInjection\TestExtension */ + /** @var DependencyInjection\TestExtension $extension */ $extension = $container->getExtension('test'); if (!$container->getParameterBag() instanceof FrozenParameterBag) { From a8f57a0a7a3b8ae1bea4032541df9e76414a12ad Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 4 Oct 2024 07:56:00 +0200 Subject: [PATCH 145/180] [FrameworkBundle] Simplify the configuration class --- DependencyInjection/Configuration.php | 31 +++++++-------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index dcb4e0eed..7a3983101 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -403,10 +403,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->end() ->end() ->arrayNode('supports') - ->beforeNormalization() - ->ifString() - ->then(fn ($v) => [$v]) - ->end() + ->beforeNormalization()->castToArray()->end() ->prototype('scalar') ->cannotBeEmpty() ->validate() @@ -535,20 +532,14 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') ->end() ->arrayNode('from') - ->beforeNormalization() - ->ifString() - ->then(fn ($v) => [$v]) - ->end() + ->beforeNormalization()->castToArray()->end() ->requiresAtLeastOneElement() ->prototype('scalar') ->cannotBeEmpty() ->end() ->end() ->arrayNode('to') - ->beforeNormalization() - ->ifString() - ->then(fn ($v) => [$v]) - ->end() + ->beforeNormalization()->castToArray()->end() ->requiresAtLeastOneElement() ->prototype('scalar') ->cannotBeEmpty() @@ -933,7 +924,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()->castToArray()->end() ->prototype('scalar')->end() ->defaultValue([]) ->end() @@ -1436,7 +1427,7 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ->end() ->prototype('array') ->performNoDeepMerging() - ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() + ->beforeNormalization()->castToArray()->end() ->prototype('scalar')->end() ->end() ->end() @@ -2226,7 +2217,7 @@ private function addNotifierSection(ArrayNodeDefinition $rootNode, callable $ena ->arrayNode('channel_policy') ->useAttributeAsKey('name') ->prototype('array') - ->beforeNormalization()->ifString()->then(fn ($v) => [$v])->end() + ->beforeNormalization()->castToArray()->end() ->prototype('scalar')->end() ->end() ->end() @@ -2442,18 +2433,12 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable ->end() ->arrayNode('block_elements') ->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) - ->end() + ->beforeNormalization()->castToArray()->end() ->scalarPrototype()->end() ->end() ->arrayNode('drop_elements') ->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) - ->end() + ->beforeNormalization()->castToArray()->end() ->scalarPrototype()->end() ->end() ->arrayNode('allow_attributes') From 8f26278831be7bdfacb46566a65402a876405b37 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 4 Oct 2024 12:54:27 +0200 Subject: [PATCH 146/180] [FrameworkBundle][Lock] Fix certain DSNs identified as service IDs --- DependencyInjection/FrameworkExtension.php | 2 +- .../Fixtures/php/lock_named.php | 2 ++ .../Fixtures/xml/lock_named.xml | 2 ++ .../Fixtures/yml/lock_named.yml | 2 ++ .../FrameworkExtensionTestCase.php | 20 +++++++++++++------ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 83bb23f2b..87a173fac 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2008,7 +2008,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont $storeDefinitions = []; foreach ($resourceStores as $resourceStore) { $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); - if (!$usedEnvs && !str_contains($resourceStore, '://')) { + if (!$usedEnvs && !str_contains($resourceStore, ':') && !\in_array($resourceStore, ['flock', 'semaphore', 'in-memory'], true)) { $resourceStore = new Reference($resourceStore); } $storeDefinition = new Definition(PersistingStoreInterface::class); diff --git a/Tests/DependencyInjection/Fixtures/php/lock_named.php b/Tests/DependencyInjection/Fixtures/php/lock_named.php index de8a8f495..cbfead830 100644 --- a/Tests/DependencyInjection/Fixtures/php/lock_named.php +++ b/Tests/DependencyInjection/Fixtures/php/lock_named.php @@ -12,5 +12,7 @@ 'bar' => 'flock', 'baz' => ['semaphore', 'flock'], 'qux' => '%env(REDIS_DSN)%', + 'corge' => 'in-memory', + 'grault' => 'mysql:host=localhost;dbname=test', ], ]); diff --git a/Tests/DependencyInjection/Fixtures/xml/lock_named.xml b/Tests/DependencyInjection/Fixtures/xml/lock_named.xml index 02659713e..7c48fa447 100644 --- a/Tests/DependencyInjection/Fixtures/xml/lock_named.xml +++ b/Tests/DependencyInjection/Fixtures/xml/lock_named.xml @@ -18,6 +18,8 @@ semaphore flock %env(REDIS_DSN)% + in-memory + mysql:host=localhost;dbname=test diff --git a/Tests/DependencyInjection/Fixtures/yml/lock_named.yml b/Tests/DependencyInjection/Fixtures/yml/lock_named.yml index 01f3af47a..04ec9fc07 100644 --- a/Tests/DependencyInjection/Fixtures/yml/lock_named.yml +++ b/Tests/DependencyInjection/Fixtures/yml/lock_named.yml @@ -12,3 +12,5 @@ framework: bar: flock baz: [semaphore, flock] qux: "%env(REDIS_DSN)%" + corge: in-memory + grault: mysql:host=localhost;dbname=test diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index fc66c889f..42017e29a 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -2423,9 +2423,9 @@ public function testDefaultLock() $storeDef = $container->getDefinition($container->getDefinition('lock.default.factory')->getArgument(0)); if (class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported()) { - self::assertEquals(new Reference('semaphore'), $storeDef->getArgument(0)); + self::assertSame('semaphore', $storeDef->getArgument(0)); } else { - self::assertEquals(new Reference('flock'), $storeDef->getArgument(0)); + self::assertSame('flock', $storeDef->getArgument(0)); } } @@ -2435,23 +2435,31 @@ public function testNamedLocks() self::assertTrue($container->hasDefinition('lock.foo.factory')); $storeDef = $container->getDefinition($container->getDefinition('lock.foo.factory')->getArgument(0)); - self::assertEquals(new Reference('semaphore'), $storeDef->getArgument(0)); + self::assertSame('semaphore', $storeDef->getArgument(0)); self::assertTrue($container->hasDefinition('lock.bar.factory')); $storeDef = $container->getDefinition($container->getDefinition('lock.bar.factory')->getArgument(0)); - self::assertEquals(new Reference('flock'), $storeDef->getArgument(0)); + self::assertSame('flock', $storeDef->getArgument(0)); self::assertTrue($container->hasDefinition('lock.baz.factory')); $storeDef = $container->getDefinition($container->getDefinition('lock.baz.factory')->getArgument(0)); self::assertIsArray($storeDefArg = $storeDef->getArgument(0)); $storeDef1 = $container->getDefinition($storeDefArg[0]); $storeDef2 = $container->getDefinition($storeDefArg[1]); - self::assertEquals(new Reference('semaphore'), $storeDef1->getArgument(0)); - self::assertEquals(new Reference('flock'), $storeDef2->getArgument(0)); + self::assertSame('semaphore', $storeDef1->getArgument(0)); + self::assertSame('flock', $storeDef2->getArgument(0)); self::assertTrue($container->hasDefinition('lock.qux.factory')); $storeDef = $container->getDefinition($container->getDefinition('lock.qux.factory')->getArgument(0)); self::assertStringContainsString('REDIS_DSN', $storeDef->getArgument(0)); + + self::assertTrue($container->hasDefinition('lock.corge.factory')); + $storeDef = $container->getDefinition($container->getDefinition('lock.corge.factory')->getArgument(0)); + self::assertSame('in-memory', $storeDef->getArgument(0)); + + self::assertTrue($container->hasDefinition('lock.grault.factory')); + $storeDef = $container->getDefinition($container->getDefinition('lock.grault.factory')->getArgument(0)); + self::assertSame('mysql:host=localhost;dbname=test', $storeDef->getArgument(0)); } public function testLockWithService() From 6e7f87fb6f189817886a00a08aa77621be0cfd2f Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 4 Oct 2024 18:58:29 +0200 Subject: [PATCH 147/180] [FrameworkBundle] Add support for setting headers to `TemplateController::__invoke()` --- Controller/TemplateController.php | 4 ++-- Tests/Controller/TemplateControllerTest.php | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Controller/TemplateController.php b/Controller/TemplateController.php index 125e04f62..c08ea347b 100644 --- a/Controller/TemplateController.php +++ b/Controller/TemplateController.php @@ -71,8 +71,8 @@ public function templateAction(string $template, ?int $maxAge = null, ?int $shar /** * @param int $statusCode The HTTP status code (200 "OK" by default) */ - public function __invoke(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200): Response + public function __invoke(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200, array $headers = []): Response { - return $this->templateAction($template, $maxAge, $sharedAge, $private, $context, $statusCode); + return $this->templateAction($template, $maxAge, $sharedAge, $private, $context, $statusCode, $headers); } } diff --git a/Tests/Controller/TemplateControllerTest.php b/Tests/Controller/TemplateControllerTest.php index 28f63ac01..1d98f4f8e 100644 --- a/Tests/Controller/TemplateControllerTest.php +++ b/Tests/Controller/TemplateControllerTest.php @@ -21,6 +21,19 @@ */ class TemplateControllerTest extends TestCase { + public function testMethodSignaturesMatch() + { + $ref = new \ReflectionClass(TemplateController::class); + + $templateActionRef = $ref->getMethod('templateAction'); + $invokeRef = $ref->getMethod('__invoke'); + + $this->assertSame( + array_map(strval(...), $templateActionRef->getParameters()), + array_map(strval(...), $invokeRef->getParameters()), + ); + } + public function testTwig() { $twig = $this->createMock(Environment::class); @@ -82,7 +95,10 @@ public function testStatusCode() $controller = new TemplateController($twig); $this->assertSame(201, $controller->templateAction($templateName, null, null, null, [], $statusCode)->getStatusCode()); + $this->assertSame(201, $controller($templateName, null, null, null, [], $statusCode)->getStatusCode()); + $this->assertSame(200, $controller->templateAction($templateName)->getStatusCode()); + $this->assertSame(200, $controller($templateName)->getStatusCode()); } public function testHeaders() @@ -96,6 +112,9 @@ public function testHeaders() $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->assertNull($controller->templateAction($templateName)->headers->get('Content-Type')); + $this->assertNull($controller($templateName)->headers->get('Content-Type')); } } From 43607eef8f1c2ef9e8d27b813b5dd463c90588eb Mon Sep 17 00:00:00 2001 From: johan Vlaar Date: Mon, 7 Oct 2024 09:47:58 +0200 Subject: [PATCH 148/180] [Webhook] Add Mailchimp webhook (fixes #50285) --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/mailer_webhook.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 87a173fac..826e8fb0f 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2677,6 +2677,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co $webhookRequestParsers = [ 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', diff --git a/Resources/config/mailer_webhook.php b/Resources/config/mailer_webhook.php index e6f6c425b..c574324db 100644 --- a/Resources/config/mailer_webhook.php +++ b/Resources/config/mailer_webhook.php @@ -13,6 +13,8 @@ use Symfony\Component\Mailer\Bridge\Brevo\RemoteEvent\BrevoPayloadConverter; use Symfony\Component\Mailer\Bridge\Brevo\Webhook\BrevoRequestParser; +use Symfony\Component\Mailer\Bridge\Mailchimp\RemoteEvent\MailchimpPayloadConverter; +use Symfony\Component\Mailer\Bridge\Mailchimp\Webhook\MailchimpRequestParser; use Symfony\Component\Mailer\Bridge\MailerSend\RemoteEvent\MailerSendPayloadConverter; use Symfony\Component\Mailer\Bridge\MailerSend\Webhook\MailerSendRequestParser; use Symfony\Component\Mailer\Bridge\Mailgun\RemoteEvent\MailgunPayloadConverter; @@ -83,5 +85,10 @@ ->set('mailer.webhook.request_parser.sweego', SweegoRequestParser::class) ->args([service('mailer.payload_converter.sweego')]) ->alias(SweegoRequestParser::class, 'mailer.webhook.request_parser.sweego') + + ->set('mailer.payload_converter.mailchimp', MailchimpPayloadConverter::class) + ->set('mailer.webhook.request_parser.mailchimp', MailchimpRequestParser::class) + ->args([service('mailer.payload_converter.mailchimp')]) + ->alias(MailchimpRequestParser::class, 'mailer.webhook.request_parser.mailchimp') ; }; From 062c0a75d537172a5403f6474bc0ab3207d15225 Mon Sep 17 00:00:00 2001 From: JoppeDC Date: Thu, 25 Jul 2024 12:32:12 +0200 Subject: [PATCH 149/180] [FrameworkBundle] Finetune `AboutCommand` --- Command/AboutCommand.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Command/AboutCommand.php b/Command/AboutCommand.php index 2c6cb440f..f4281cd21 100644 --- a/Command/AboutCommand.php +++ b/Command/AboutCommand.php @@ -25,6 +25,7 @@ * A console command to display information about the current installation. * * @author Roland Franssen + * @author Joppe De Cuyper * * @final */ @@ -57,6 +58,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $buildDir = $kernel->getCacheDir(); } + $xdebugMode = getenv('XDEBUG_MODE') ?: \ini_get('xdebug.mode'); + $rows = [ ['Symfony'], new TableSeparator(), @@ -81,9 +84,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int ['Architecture', (\PHP_INT_SIZE * 8).' bits'], ['Intl locale', class_exists(\Locale::class, false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a'], ['Timezone', date_default_timezone_get().' ('.(new \DateTimeImmutable())->format(\DateTimeInterface::W3C).')'], - ['OPcache', \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) ? 'true' : 'false'], - ['APCu', \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOL) ? 'true' : 'false'], - ['Xdebug', \extension_loaded('xdebug') ? 'true' : 'false'], + ['OPcache', \extension_loaded('Zend OPcache') ? (filter_var(\ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) ? 'Enabled' : 'Not enabled') : 'Not installed'], + ['APCu', \extension_loaded('apcu') ? (filter_var(\ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? 'Enabled' : 'Not enabled') : 'Not installed'], + ['Xdebug', \extension_loaded('xdebug') ? ($xdebugMode && $xdebugMode !== 'off' ? 'Enabled (' . $xdebugMode . ')' : 'Not enabled') : 'Not installed'], ]; $io->table([], $rows); From 91e5b6517da49b058346d33528184e5a0a0f28bf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 26 Aug 2024 16:50:35 +0200 Subject: [PATCH 150/180] [Security] Implement stateless headers/cookies-based CSRF protection --- CHANGELOG.md | 2 ++ DependencyInjection/Configuration.php | 25 ++++++++++++++--- DependencyInjection/FrameworkExtension.php | 27 ++++++++++++++++--- Resources/config/form_csrf.php | 2 ++ Resources/config/schema/symfony-1.0.xsd | 13 +++++++++ Resources/config/security_csrf.php | 14 ++++++++++ .../DependencyInjection/ConfigurationTest.php | 7 ++++- composer.json | 2 +- 8 files changed, 84 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19ce70b6b..3d6acb26a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ CHANGELOG * Deprecate making `cache.app` adapter taggable, use the `cache.app.taggable` adapter instead * Enable `json_decode_detailed_errors` in the default serializer context in debug mode by default when `seld/jsonlint` is installed * Register `Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter` as a service named `serializer.name_converter.snake_case_to_camel_case` if available + * Add `framework.csrf_protection.stateless_token_ids`, `.cookie_name`, and `.check_header` options to use stateless headers/cookies-based CSRF protection + * Add `framework.form.csrf_protection.field_attr` option * Deprecate `session.sid_length` and `session.sid_bits_per_character` config options * Add the ability to use an existing service as a lock/semaphore resource * Add support for configuring multiple serializer instances via the configuration diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 7a3983101..9abd10e73 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -209,9 +209,22 @@ private function addCsrfSection(ArrayNodeDefinition $rootNode): void ->treatTrueLike(['enabled' => true]) ->treatNullLike(['enabled' => true]) ->addDefaultsIfNotSet() + ->fixXmlConfig('stateless_token_id') ->children() - // defaults to framework.session.enabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) - ->booleanNode('enabled')->defaultNull()->end() + // defaults to framework.csrf_protection.stateless_token_ids || framework.session.enabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) + ->scalarNode('enabled')->defaultNull()->end() + ->arrayNode('stateless_token_ids') + ->scalarPrototype()->end() + ->info('Enable headers/cookies-based CSRF validation for the listed token ids.') + ->end() + ->scalarNode('check_header') + ->defaultFalse() + ->info('Whether to check the CSRF token in a header in addition to a cookie when using stateless protection.') + ->end() + ->scalarNode('cookie_name') + ->defaultValue('csrf-token') + ->info('The name of the cookie to use when using stateless protection.') + ->end() ->end() ->end() ->end() @@ -232,8 +245,14 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->treatNullLike(['enabled' => true]) ->addDefaultsIfNotSet() ->children() - ->booleanNode('enabled')->defaultNull()->end() // defaults to framework.csrf_protection.enabled + ->scalarNode('enabled')->defaultNull()->end() // defaults to framework.csrf_protection.enabled + ->scalarNode('token_id')->defaultNull()->end() ->scalarNode('field_name')->defaultValue('_token')->end() + ->arrayNode('field_attr') + ->performNoDeepMerging() + ->scalarPrototype()->end() + ->defaultValue(['data-controller' => 'csrf-protection']) + ->end() ->end() ->end() ->end() diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 826e8fb0f..139379771 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -464,7 +464,7 @@ public function load(array $configs, ContainerBuilder $container): void // csrf depends on session being registered if (null === $config['csrf_protection']['enabled']) { - $this->writeConfigEnabled('csrf_protection', $this->readConfigEnabled('session', $container, $config['session']) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']); + $this->writeConfigEnabled('csrf_protection', $config['csrf_protection']['stateless_token_ids'] || $this->readConfigEnabled('session', $container, $config['session']) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']); } $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); @@ -765,6 +765,10 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont $container->setParameter('form.type_extension.csrf.enabled', true); $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']); + $container->setParameter('form.type_extension.csrf.field_attr', $config['form']['csrf_protection']['field_attr']); + + $container->getDefinition('form.type_extension.csrf') + ->replaceArgument(7, $config['form']['csrf_protection']['token_id']); } else { $container->setParameter('form.type_extension.csrf.enabled', false); } @@ -1815,8 +1819,7 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild if (!class_exists(\Symfony\Component\Security\Csrf\CsrfToken::class)) { throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".'); } - - if (!$this->isInitializedConfigEnabled('session')) { + if (!$config['stateless_token_ids'] && !$this->isInitializedConfigEnabled('session')) { throw new \LogicException('CSRF protection needs sessions to be enabled.'); } @@ -1826,6 +1829,24 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild if (!class_exists(CsrfExtension::class)) { $container->removeDefinition('twig.extension.security_csrf'); } + + if (!$config['stateless_token_ids']) { + $container->removeDefinition('security.csrf.same_origin_token_manager'); + + return; + } + + $container->getDefinition('security.csrf.same_origin_token_manager') + ->replaceArgument(3, $config['stateless_token_ids']) + ->replaceArgument(4, $config['check_header']) + ->replaceArgument(5, $config['cookie_name']); + + if (!$this->isInitializedConfigEnabled('session')) { + $container->setAlias('security.csrf.token_manager', 'security.csrf.same_origin_token_manager'); + $container->getDefinition('security.csrf.same_origin_token_manager') + ->setDecoratedService(null) + ->replaceArgument(2, null); + } } private function registerSerializerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void diff --git a/Resources/config/form_csrf.php b/Resources/config/form_csrf.php index c8e5e973e..c63d087c8 100644 --- a/Resources/config/form_csrf.php +++ b/Resources/config/form_csrf.php @@ -23,6 +23,8 @@ service('translator')->nullOnInvalid(), param('validator.translation_domain'), service('form.server_params'), + param('form.type_extension.csrf.field_attr'), + abstract_arg('framework.form.csrf_protection.token_id'), ]) ->tag('form.type_extension') ; diff --git a/Resources/config/schema/symfony-1.0.xsd b/Resources/config/schema/symfony-1.0.xsd index 64e9c76cb..ed7cc744f 100644 --- a/Resources/config/schema/symfony-1.0.xsd +++ b/Resources/config/schema/symfony-1.0.xsd @@ -71,12 +71,25 @@ + + + + + + + + + + + + + diff --git a/Resources/config/security_csrf.php b/Resources/config/security_csrf.php index bad2284bf..ca5d69be3 100644 --- a/Resources/config/security_csrf.php +++ b/Resources/config/security_csrf.php @@ -15,6 +15,7 @@ use Symfony\Bridge\Twig\Extension\CsrfRuntime; use Symfony\Component\Security\Csrf\CsrfTokenManager; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Csrf\SameOriginCsrfTokenManager; use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; @@ -46,5 +47,18 @@ ->set('twig.extension.security_csrf', CsrfExtension::class) ->tag('twig.extension') + + ->set('security.csrf.same_origin_token_manager', SameOriginCsrfTokenManager::class) + ->decorate('security.csrf.token_manager') + ->args([ + service('request_stack'), + service('logger')->nullOnInvalid(), + service('.inner'), + abstract_arg('framework.csrf_protection.stateless_token_ids'), + abstract_arg('framework.csrf_protection.check_header'), + abstract_arg('framework.csrf_protection.cookie_name'), + ]) + ->tag('monolog.logger', ['channel' => 'request']) + ->tag('kernel.event_listener', ['event' => 'kernel.response', 'method' => 'onKernelResponse']) ; }; diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index c569a852d..53706d2e0 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -715,13 +715,18 @@ protected static function getBundleDefaultConfig() 'trusted_proxies' => ['%env(default::SYMFONY_TRUSTED_PROXIES)%'], 'trusted_headers' => ['%env(default::SYMFONY_TRUSTED_HEADERS)%'], 'csrf_protection' => [ - 'enabled' => false, + 'enabled' => null, + 'cookie_name' => 'csrf-token', + 'check_header' => false, + 'stateless_token_ids' => [], ], 'form' => [ 'enabled' => !class_exists(FullStack::class), 'csrf_protection' => [ 'enabled' => null, // defaults to csrf_protection.enabled 'field_name' => '_token', + 'field_attr' => ['data-controller' => 'csrf-protection'], + 'token_id' => null, ], ], 'esi' => ['enabled' => false], diff --git a/composer.json b/composer.json index 3613ba8eb..af83a9a13 100644 --- a/composer.json +++ b/composer.json @@ -96,7 +96,7 @@ "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/serializer": "<6.4", - "symfony/security-csrf": "<6.4", + "symfony/security-csrf": "<7.2", "symfony/security-core": "<6.4", "symfony/stopwatch": "<6.4", "symfony/translation": "<6.4", From d609ce6ce34bb4c295f55c5ea6eea93b4f7954ee Mon Sep 17 00:00:00 2001 From: HypeMC Date: Thu, 10 Oct 2024 10:12:22 +0200 Subject: [PATCH 151/180] [FrameworkBundle] Fix `NullStore` registration --- DependencyInjection/FrameworkExtension.php | 2 +- Tests/DependencyInjection/Fixtures/php/lock_named.php | 1 + Tests/DependencyInjection/Fixtures/xml/lock_named.xml | 1 + Tests/DependencyInjection/Fixtures/yml/lock_named.yml | 1 + Tests/DependencyInjection/FrameworkExtensionTestCase.php | 4 ++++ 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 139379771..62277c9bb 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2029,7 +2029,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont $storeDefinitions = []; foreach ($resourceStores as $resourceStore) { $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); - if (!$usedEnvs && !str_contains($resourceStore, ':') && !\in_array($resourceStore, ['flock', 'semaphore', 'in-memory'], true)) { + if (!$usedEnvs && !str_contains($resourceStore, ':') && !\in_array($resourceStore, ['flock', 'semaphore', 'in-memory', 'null'], true)) { $resourceStore = new Reference($resourceStore); } $storeDefinition = new Definition(PersistingStoreInterface::class); diff --git a/Tests/DependencyInjection/Fixtures/php/lock_named.php b/Tests/DependencyInjection/Fixtures/php/lock_named.php index cbfead830..c03a7fa71 100644 --- a/Tests/DependencyInjection/Fixtures/php/lock_named.php +++ b/Tests/DependencyInjection/Fixtures/php/lock_named.php @@ -14,5 +14,6 @@ 'qux' => '%env(REDIS_DSN)%', 'corge' => 'in-memory', 'grault' => 'mysql:host=localhost;dbname=test', + 'garply' => 'null', ], ]); diff --git a/Tests/DependencyInjection/Fixtures/xml/lock_named.xml b/Tests/DependencyInjection/Fixtures/xml/lock_named.xml index 7c48fa447..b8d4b4a3f 100644 --- a/Tests/DependencyInjection/Fixtures/xml/lock_named.xml +++ b/Tests/DependencyInjection/Fixtures/xml/lock_named.xml @@ -20,6 +20,7 @@ %env(REDIS_DSN)% in-memory mysql:host=localhost;dbname=test + null diff --git a/Tests/DependencyInjection/Fixtures/yml/lock_named.yml b/Tests/DependencyInjection/Fixtures/yml/lock_named.yml index 04ec9fc07..631574030 100644 --- a/Tests/DependencyInjection/Fixtures/yml/lock_named.yml +++ b/Tests/DependencyInjection/Fixtures/yml/lock_named.yml @@ -14,3 +14,4 @@ framework: qux: "%env(REDIS_DSN)%" corge: in-memory grault: mysql:host=localhost;dbname=test + garply: 'null' diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 4bccbb71f..016ae507b 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -2460,6 +2460,10 @@ public function testNamedLocks() self::assertTrue($container->hasDefinition('lock.grault.factory')); $storeDef = $container->getDefinition($container->getDefinition('lock.grault.factory')->getArgument(0)); self::assertSame('mysql:host=localhost;dbname=test', $storeDef->getArgument(0)); + + self::assertTrue($container->hasDefinition('lock.garply.factory')); + $storeDef = $container->getDefinition($container->getDefinition('lock.garply.factory')->getArgument(0)); + self::assertSame('null', $storeDef->getArgument(0)); } public function testLockWithService() From 6800168c2ea7c4b97d027ef06c8f669474773e83 Mon Sep 17 00:00:00 2001 From: Yi-Jyun Pan Date: Thu, 10 Oct 2024 18:09:26 +0800 Subject: [PATCH 152/180] [Notifier] Add LINE Bot bridge --- DependencyInjection/FrameworkExtension.php | 1 + Resources/config/notifier_transports.php | 1 + 2 files changed, 2 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 139379771..c4ea185b8 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2839,6 +2839,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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', diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 7c8002993..073eda08b 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -32,6 +32,7 @@ 'fake-chat' => Bridge\FakeChat\FakeChatTransportFactory::class, 'firebase' => Bridge\Firebase\FirebaseTransportFactory::class, 'google-chat' => Bridge\GoogleChat\GoogleChatTransportFactory::class, + 'line-bot' => Bridge\LineBot\LineBotTransportFactory::class, 'line-notify' => Bridge\LineNotify\LineNotifyTransportFactory::class, 'linked-in' => Bridge\LinkedIn\LinkedInTransportFactory::class, 'mastodon' => Bridge\Mastodon\MastodonTransportFactory::class, From 0bb13689c1d865c2395d0b2228c240509daedc92 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 17 Oct 2024 13:48:28 +0200 Subject: [PATCH 153/180] [FrameworkBundle] Bump `symfony/http-kernel` --- Tests/Functional/ApiAttributesTest.php | 26 -------------------------- composer.json | 6 +++--- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/Tests/Functional/ApiAttributesTest.php b/Tests/Functional/ApiAttributesTest.php index 350446dc7..cf5c384ba 100644 --- a/Tests/Functional/ApiAttributesTest.php +++ b/Tests/Functional/ApiAttributesTest.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; -use Composer\InstalledVersions; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -165,18 +164,6 @@ public static function mapQueryStringProvider(): iterable } JSON; - $httpKernelVersion = InstalledVersions::getVersion('symfony/http-kernel'); - if ($httpKernelVersion && version_compare($httpKernelVersion, '7.2.0', '<')) { - $expectedResponse = <<<'JSON' - { - "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", - "title": "An error occurred", - "status": 404, - "detail": "Not Found" - } - JSON; - } - yield 'empty query string mapping non-nullable attribute without default value' => [ 'uri' => '/map-query-string-to-non-nullable-attribute-without-default-value.json', 'query' => [], @@ -750,19 +737,6 @@ public static function mapRequestPayloadProvider(): iterable } JSON; - $httpKernelVersion = InstalledVersions::getVersion('symfony/http-kernel'); - if ($httpKernelVersion && version_compare($httpKernelVersion, '7.2.0', '<')) { - $expectedStatusCode = 422; - $expectedResponse = <<<'JSON' - { - "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", - "title": "An error occurred", - "status": 422, - "detail": "Unprocessable Content" - } - JSON; - } - yield 'empty request mapping non-nullable attribute without default value' => [ 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', 'format' => 'json', diff --git a/composer.json b/composer.json index af83a9a13..8d97985e7 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "symfony/error-handler": "^6.4|^7.0", "symfony/event-dispatcher": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", + "symfony/http-kernel": "^7.2", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "^7.1", "symfony/finder": "^6.4|^7.0", @@ -59,7 +59,7 @@ "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^6.4|^7.0", "symfony/semaphore": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/serializer": "^7.1", "symfony/stopwatch": "^6.4|^7.0", "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", @@ -95,9 +95,9 @@ "symfony/property-access": "<6.4", "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", - "symfony/serializer": "<6.4", "symfony/security-csrf": "<7.2", "symfony/security-core": "<6.4", + "symfony/serializer": "<7.1", "symfony/stopwatch": "<6.4", "symfony/translation": "<6.4", "symfony/twig-bridge": "<6.4", From 5ee045beeb38e62931be7d0dfdc0194c168da0c3 Mon Sep 17 00:00:00 2001 From: Mathieu Santostefano Date: Sun, 8 Sep 2024 13:40:02 +0200 Subject: [PATCH 154/180] Add Sweego Notifier bridge --- DependencyInjection/FrameworkExtension.php | 2 ++ Resources/config/notifier_transports.php | 1 + Resources/config/notifier_webhook.php | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index c4ea185b8..a19c5a863 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2881,6 +2881,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ 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', @@ -2948,6 +2949,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ $loader->load('notifier_webhook.php'); $webhookRequestParsers = [ + 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', ]; diff --git a/Resources/config/notifier_transports.php b/Resources/config/notifier_transports.php index 073eda08b..f28007dec 100644 --- a/Resources/config/notifier_transports.php +++ b/Resources/config/notifier_transports.php @@ -108,6 +108,7 @@ 'smsense' => Bridge\Smsense\SmsenseTransportFactory::class, 'smsmode' => Bridge\Smsmode\SmsmodeTransportFactory::class, 'spot-hit' => Bridge\SpotHit\SpotHitTransportFactory::class, + 'sweego' => Bridge\Sweego\SweegoTransportFactory::class, 'telnyx' => Bridge\Telnyx\TelnyxTransportFactory::class, 'termii' => Bridge\Termii\TermiiTransportFactory::class, 'turbo-sms' => Bridge\TurboSms\TurboSmsTransportFactory::class, diff --git a/Resources/config/notifier_webhook.php b/Resources/config/notifier_webhook.php index fc541fd99..6447f4139 100644 --- a/Resources/config/notifier_webhook.php +++ b/Resources/config/notifier_webhook.php @@ -11,11 +11,15 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; +use Symfony\Component\Notifier\Bridge\Sweego\Webhook\SweegoRequestParser; use Symfony\Component\Notifier\Bridge\Twilio\Webhook\TwilioRequestParser; use Symfony\Component\Notifier\Bridge\Vonage\Webhook\VonageRequestParser; return static function (ContainerConfigurator $container) { $container->services() + ->set('notifier.webhook.request_parser.sweego', SweegoRequestParser::class) + ->alias(SweegoRequestParser::class, 'notifier.webhook.request_parser.sweego') + ->set('notifier.webhook.request_parser.twilio', TwilioRequestParser::class) ->alias(TwilioRequestParser::class, 'notifier.webhook.request_parser.twilio') From 6e695b99d307892e64ccedef0b95e01516092eb2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 22 Oct 2024 11:46:04 +0200 Subject: [PATCH 155/180] do not access typed properties before initialization --- KernelBrowser.php | 2 +- Tests/KernelBrowserTest.php | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/KernelBrowser.php b/KernelBrowser.php index e06b9a056..a77f97ea0 100644 --- a/KernelBrowser.php +++ b/KernelBrowser.php @@ -56,7 +56,7 @@ public function getKernel(): KernelInterface */ public function getProfile(): HttpProfile|false|null { - if (null === $this->response || !$this->getContainer()->has('profiler')) { + if (!isset($this->response) || !$this->getContainer()->has('profiler')) { return false; } diff --git a/Tests/KernelBrowserTest.php b/Tests/KernelBrowserTest.php index 1e462f7d0..4e62b5ee7 100644 --- a/Tests/KernelBrowserTest.php +++ b/Tests/KernelBrowserTest.php @@ -14,6 +14,7 @@ use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Tests\Functional\AbstractWebTestCase; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\KernelInterface; class KernelBrowserTest extends AbstractWebTestCase { @@ -61,6 +62,13 @@ public function testRequestAfterKernelShutdownAndPerformedRequest() $client->request('GET', '/'); } + public function testGetProfileWithoutRequest() + { + $browser = new KernelBrowser($this->createMock(KernelInterface::class)); + + $this->assertFalse($browser->getProfile()); + } + private function getKernelMock() { $mock = $this->getMockBuilder($this->getKernelClass()) From 81bf4e0b09ad76c7a01e4d0abe6785354e5f4e57 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Wed, 14 Aug 2024 15:51:51 +0200 Subject: [PATCH 156/180] [TypeInfo] Redesign Type methods and nullability --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index af83a9a13..fd058671c 100644 --- a/composer.json +++ b/composer.json @@ -64,7 +64,7 @@ "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.1", + "symfony/type-info": "^7.2", "symfony/validator": "^6.4|^7.0", "symfony/workflow": "^6.4|^7.0", "symfony/yaml": "^6.4|^7.0", From 47e180938e1468a0d07ffbaca83e9310b5826147 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 18 Oct 2024 16:04:52 +0200 Subject: [PATCH 157/180] Remove always true/false occurrences --- Console/Descriptor/TextDescriptor.php | 4 ++-- Tests/Command/XliffLintCommandTest.php | 4 +--- Tests/Command/YamlLintCommandTest.php | 4 +--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index 6ee8b04a1..5efaab496 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -172,7 +172,7 @@ protected function describeContainerService(object $service, array $options = [] $options['output']->table( ['Service ID', 'Class'], [ - [$options['id'] ?? '-', $service::class], + [$options['id'], $service::class], ] ); } @@ -333,7 +333,7 @@ protected function describeContainerDefinition(Definition $definition, array $op $tableRows[] = ['Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no']; if ($definition->getFile()) { - $tableRows[] = ['Required File', $definition->getFile() ?: '-']; + $tableRows[] = ['Required File', $definition->getFile()]; } if ($factory = $definition->getFactory()) { diff --git a/Tests/Command/XliffLintCommandTest.php b/Tests/Command/XliffLintCommandTest.php index db32bc19c..d5495ada9 100644 --- a/Tests/Command/XliffLintCommandTest.php +++ b/Tests/Command/XliffLintCommandTest.php @@ -64,9 +64,7 @@ private function createCommandTester($application = null): CommandTester $command = $application->find('lint:xliff'); - if ($application) { - $command->setApplication($application); - } + $command->setApplication($application); return new CommandTester($command); } diff --git a/Tests/Command/YamlLintCommandTest.php b/Tests/Command/YamlLintCommandTest.php index 08f4a7526..ec2093119 100644 --- a/Tests/Command/YamlLintCommandTest.php +++ b/Tests/Command/YamlLintCommandTest.php @@ -112,9 +112,7 @@ private function createCommandTester($application = null): CommandTester $command = $application->find('lint:yaml'); - if ($application) { - $command->setApplication($application); - } + $command->setApplication($application); return new CommandTester($command); } From cd12cd43c0be653c8dfc4beefc1dec687a7e1e98 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 23 Oct 2024 10:11:04 +0200 Subject: [PATCH 158/180] revert allowing Twig 4 As Twig 4 will not be released before Symfony 7.2 we should not claim compatibility before a stable Twig 4 release. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8d97985e7..9b3e7c86e 100644 --- a/composer.json +++ b/composer.json @@ -73,7 +73,7 @@ "symfony/web-link": "^6.4|^7.0", "symfony/webhook": "^7.2", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^3.12|^4.0" + "twig/twig": "^3.12" }, "conflict": { "doctrine/persistence": "<1.3", From c2c08eb9aa3b9c73fa2ad5531d4b174f6085da5c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 23 Oct 2024 10:20:11 +0200 Subject: [PATCH 159/180] fix null store handling in XML configs --- DependencyInjection/FrameworkExtension.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index dab5f0c69..a7749cd30 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2028,6 +2028,10 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont // Generate stores $storeDefinitions = []; foreach ($resourceStores as $resourceStore) { + if (null === $resourceStore) { + $resourceStore = 'null'; + } + $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); if (!$usedEnvs && !str_contains($resourceStore, ':') && !\in_array($resourceStore, ['flock', 'semaphore', 'in-memory', 'null'], true)) { $resourceStore = new Reference($resourceStore); From 255a07d200f0e72fb2f4d90d082fd73c2b613ecc Mon Sep 17 00:00:00 2001 From: jawira Date: Sun, 6 Oct 2024 10:45:55 +0200 Subject: [PATCH 160/180] [FrameworkBundle] Add `--no-fill` option to `translation:extract` command --- CHANGELOG.md | 1 + Command/TranslationUpdateCommand.php | 25 +++++++++--- .../Command/TranslationUpdateCommandTest.php | 40 +++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d6acb26a..3227eddc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ CHANGELOG * Add the ability to use an existing service as a lock/semaphore resource * Add support for configuring multiple serializer instances via the configuration * Add support for `SYMFONY_TRUSTED_PROXIES`, `SYMFONY_TRUSTED_HEADERS`, `SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER` and `SYMFONY_TRUSTED_HOSTS` env vars + * Add `--no-fill` option to `translation:extract` command 7.1 --- diff --git a/Command/TranslationUpdateCommand.php b/Command/TranslationUpdateCommand.php index 04f812146..b26d3f9ad 100644 --- a/Command/TranslationUpdateCommand.php +++ b/Command/TranslationUpdateCommand.php @@ -19,7 +19,6 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\HttpKernel\KernelInterface; @@ -49,6 +48,7 @@ class TranslationUpdateCommand extends Command 'xlf12' => ['xlf', '1.2'], 'xlf20' => ['xlf', '2.0'], ]; + private const NO_FILL_PREFIX = "\0NoFill\0"; public function __construct( private TranslationWriterInterface $writer, @@ -71,6 +71,7 @@ protected function configure(): void new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'), + new InputOption('no-fill', null, InputOption::VALUE_NONE, 'Extract translation keys without filling in values'), new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf12'), new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), @@ -85,7 +86,8 @@ protected function configure(): void the new ones into the translation files. When new translation strings are found it can automatically add a prefix to the translation -message. +message. However, if the --no-fill option is used, the --prefix +option has no effect, since the translation values are left empty. Example running against a Bundle (AcmeBundle) @@ -113,9 +115,6 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { - $io = new SymfonyStyle($input, $output); - $errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io; - $io = new SymfonyStyle($input, $output); $errorIo = $io->getErrorStyle(); @@ -181,7 +180,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->comment(\sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); $io->comment('Parsing templates...'); - $extractedCatalogue = $this->extractMessages($input->getArgument('locale'), $codePaths, $input->getOption('prefix')); + $prefix = $input->getOption('no-fill') ? self::NO_FILL_PREFIX : $input->getOption('prefix'); + $extractedCatalogue = $this->extractMessages($input->getArgument('locale'), $codePaths, $prefix); $io->comment('Loading translation files...'); $currentCatalogue = $this->loadCurrentMessages($input->getArgument('locale'), $transPaths); @@ -271,6 +271,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $operationResult = $this->sortCatalogue($operationResult, $sort); } + if (true === $input->getOption('no-fill')) { + $this->removeNoFillTranslations($operationResult); + } + $this->writer->write($operationResult, $format, ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $xliffVersion, 'as_tree' => $input->getOption('as-tree'), 'inline' => $input->getOption('as-tree') ?? 0]); if (true === $input->getOption('dump-messages')) { @@ -485,4 +489,13 @@ private function getRootCodePaths(KernelInterface $kernel): array return $codePaths; } + + 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'); + } + } + } } diff --git a/Tests/Command/TranslationUpdateCommandTest.php b/Tests/Command/TranslationUpdateCommandTest.php index 2304e75ad..3a1bd8e37 100644 --- a/Tests/Command/TranslationUpdateCommandTest.php +++ b/Tests/Command/TranslationUpdateCommandTest.php @@ -21,6 +21,7 @@ use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; use Symfony\Component\Translation\Reader\TranslationReader; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\Writer\TranslationWriter; @@ -176,6 +177,45 @@ public function testFilterDuplicateTransPaths() $this->assertEquals($expectedPaths, $filteredTransPaths); } + /** + * @dataProvider removeNoFillProvider + */ + public function testRemoveNoFillTranslationsMethod($noFillCounter, $messages) + { + // Preparing mock + $operation = $this->createMock(MessageCatalogueInterface::class); + $operation + ->method('all') + ->with('messages') + ->willReturn($messages); + $operation + ->expects($this->exactly($noFillCounter)) + ->method('set'); + + // Calling private method + $translationUpdate = $this->createMock(TranslationUpdateCommand::class); + $reflection = new \ReflectionObject($translationUpdate); + $method = $reflection->getMethod('removeNoFillTranslations'); + $method->invokeArgs($translationUpdate, [$operation]); + } + + public function removeNoFillProvider(): array + { + return [ + [0, []], + [0, ['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz']], + [0, ['foo' => "\0foo"]], + [0, ['foo' => "foo\0NoFill\0"]], + [0, ['foo' => "f\0NoFill\000"]], + [0, ['foo' => 'foo', 'bar' => 'bar']], + [1, ['foo' => "\0NoFill\0foo"]], + [1, ['foo' => "\0NoFill\0foo", 'bar' => 'bar']], + [1, ['foo' => 'foo', 'bar' => "\0NoFill\0bar"]], + [2, ['foo' => "\0NoFill\0foo", 'bar' => "\0NoFill\0bar"]], + [3, ['foo' => "\0NoFill\0foo", 'bar' => "\0NoFill\0bar", 'baz' => "\0NoFill\0baz"]], + ]; + } + protected function setUp(): void { $this->fs = new Filesystem(); From 70a802fd68a97e4864c33262ce50c8ba1af5b227 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 23 Oct 2024 22:23:29 +0200 Subject: [PATCH 161/180] make data provider static --- Tests/Command/TranslationUpdateCommandTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Command/TranslationUpdateCommandTest.php b/Tests/Command/TranslationUpdateCommandTest.php index 3a1bd8e37..f803c2908 100644 --- a/Tests/Command/TranslationUpdateCommandTest.php +++ b/Tests/Command/TranslationUpdateCommandTest.php @@ -199,7 +199,7 @@ public function testRemoveNoFillTranslationsMethod($noFillCounter, $messages) $method->invokeArgs($translationUpdate, [$operation]); } - public function removeNoFillProvider(): array + public static function removeNoFillProvider(): array { return [ [0, []], From 7a46f7de39c92cdc29fd86beeb6f16ad1a3e5dd8 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Wed, 16 Oct 2024 21:38:41 +0200 Subject: [PATCH 162/180] [Routing] Rename annotations to attribute in `AttributeClassLoader` --- Routing/AttributeRouteControllerLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Routing/AttributeRouteControllerLoader.php b/Routing/AttributeRouteControllerLoader.php index 7e43e1af5..1d3d547c8 100644 --- a/Routing/AttributeRouteControllerLoader.php +++ b/Routing/AttributeRouteControllerLoader.php @@ -26,7 +26,7 @@ class AttributeRouteControllerLoader extends AttributeClassLoader /** * Configures the _controller default parameter of a given Route instance. */ - protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot): void + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $attr): void { if ('__invoke' === $method->getName()) { $route->setDefault('_controller', $class->getName()); From 3bf00830d8737115dcc47143e31e36e49729dd52 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 12 Nov 2024 09:53:35 +0100 Subject: [PATCH 163/180] ensure that the validator.translation_domain parameter is always set --- DependencyInjection/FrameworkExtension.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index a7749cd30..b7d0bfe90 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -219,6 +219,10 @@ public function load(array $configs, ContainerBuilder $container): void throw new \LogicException('Requiring the "symfony/symfony" package is unsupported; replace it with standalone components instead.'); } + if (!ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/form'])) { + $container->setParameter('validator.translation_domain', 'validators'); + } + $loader->load('web.php'); $loader->load('services.php'); $loader->load('fragment_renderer.php'); @@ -479,8 +483,6 @@ public function load(array $configs, ContainerBuilder $container): void if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/form'])) { $this->writeConfigEnabled('validation', true, $config['validation']); } else { - $container->setParameter('validator.translation_domain', 'validators'); - $container->removeDefinition('form.type_extension.form.validator'); $container->removeDefinition('form.type_guesser.validator'); } From f95434900e37e035585c57dfadd2315c898027c4 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Thu, 14 Nov 2024 13:01:20 +0100 Subject: [PATCH 164/180] [TypeInfo][Serializer][PropertyInfo][Validator] TypeInfo 7.1 compatibility --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b4f474bb9..9b3e7c86e 100644 --- a/composer.json +++ b/composer.json @@ -64,7 +64,7 @@ "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.2", + "symfony/type-info": "^7.1", "symfony/validator": "^6.4|^7.0", "symfony/workflow": "^6.4|^7.0", "symfony/yaml": "^6.4|^7.0", From 15df69b03ab9d2d06663f08c2dd6ecc0f4aad76e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Nov 2024 10:52:39 +0100 Subject: [PATCH 165/180] [FrameworkBundle] Don't auto-register form/csrf when the corresponding components are not installed --- DependencyInjection/Configuration.php | 8 +++++-- DependencyInjection/FrameworkExtension.php | 21 ++++++++++++------- .../Fixtures/php/form_csrf_disabled.php | 1 + .../Fixtures/php/form_no_csrf.php | 1 + .../DependencyInjection/Fixtures/php/full.php | 1 + .../DependencyInjection/Fixtures/xml/full.xml | 2 +- .../Fixtures/yml/form_csrf_disabled.yml | 1 + .../Fixtures/yml/form_no_csrf.yml | 1 + .../DependencyInjection/Fixtures/yml/full.yml | 1 + 9 files changed, 26 insertions(+), 11 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 9abd10e73..9754cb078 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -211,7 +211,7 @@ private function addCsrfSection(ArrayNodeDefinition $rootNode): void ->addDefaultsIfNotSet() ->fixXmlConfig('stateless_token_id') ->children() - // defaults to framework.csrf_protection.stateless_token_ids || framework.session.enabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) + // defaults to (framework.csrf_protection.stateless_token_ids || framework.session.enabled) && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) ->scalarNode('enabled')->defaultNull()->end() ->arrayNode('stateless_token_ids') ->scalarPrototype()->end() @@ -237,8 +237,12 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->children() ->arrayNode('form') ->info('Form configuration') - ->{$enableIfStandalone('symfony/form', Form::class)}() + ->treatFalseLike(['enabled' => false]) + ->treatTrueLike(['enabled' => true]) + ->treatNullLike(['enabled' => true]) + ->addDefaultsIfNotSet() ->children() + ->scalarNode('enabled')->defaultNull()->end() // defaults to !class_exists(FullStack::class) && class_exists(Form::class) ->arrayNode('csrf_protection') ->treatFalseLike(['enabled' => false]) ->treatTrueLike(['enabled' => true]) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index b7d0bfe90..73101912a 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -278,6 +278,19 @@ public function load(array $configs, ContainerBuilder $container): void $this->readConfigEnabled('profiler', $container, $config['profiler']); $this->readConfigEnabled('workflows', $container, $config['workflows']); + // csrf depends on session or stateless token ids being registered + if (null === $config['csrf_protection']['enabled']) { + $this->writeConfigEnabled('csrf_protection', ($config['csrf_protection']['stateless_token_ids'] || $this->readConfigEnabled('session', $container, $config['session'])) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']); + } + + if (null === $config['form']['enabled']) { + $this->writeConfigEnabled('form', !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle']), $config['form']); + } + + if (null === $config['form']['csrf_protection']['enabled']) { + $this->writeConfigEnabled('form.csrf_protection', $config['csrf_protection']['enabled'], $config['form']['csrf_protection']); + } + // A translator must always be registered (as support is included by // default in the Form and Validator component). If disabled, an identity // translator will be used and everything will still work as expected. @@ -466,10 +479,6 @@ public function load(array $configs, ContainerBuilder $container): void $container->removeDefinition('test.session.listener'); } - // csrf depends on session being registered - if (null === $config['csrf_protection']['enabled']) { - $this->writeConfigEnabled('csrf_protection', $config['csrf_protection']['stateless_token_ids'] || $this->readConfigEnabled('session', $container, $config['session']) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']); - } $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); // form depends on csrf being registered @@ -754,10 +763,6 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont { $loader->load('form.php'); - if (null === $config['form']['csrf_protection']['enabled']) { - $this->writeConfigEnabled('form.csrf_protection', $config['csrf_protection']['enabled'], $config['form']['csrf_protection']); - } - if ($this->readConfigEnabled('form.csrf_protection', $container, $config['form']['csrf_protection'])) { if (!$container->hasDefinition('security.csrf.token_generator')) { throw new \LogicException('To use form CSRF protection, "framework.csrf_protection" must be enabled.'); diff --git a/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php b/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php index 981498609..809b40be4 100644 --- a/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php +++ b/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php @@ -4,6 +4,7 @@ 'annotations' => false, 'csrf_protection' => false, 'form' => [ + 'enabled' => true, 'csrf_protection' => true, ], 'http_method_override' => false, diff --git a/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php b/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php index 7c052c9ff..5c63ed068 100644 --- a/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php +++ b/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php @@ -6,6 +6,7 @@ 'handle_all_throwables' => true, 'php_errors' => ['log' => true], 'form' => [ + 'enabled' => true, 'csrf_protection' => [ 'enabled' => false, ], diff --git a/Tests/DependencyInjection/Fixtures/php/full.php b/Tests/DependencyInjection/Fixtures/php/full.php index 0a32ce8b3..a728a4483 100644 --- a/Tests/DependencyInjection/Fixtures/php/full.php +++ b/Tests/DependencyInjection/Fixtures/php/full.php @@ -6,6 +6,7 @@ 'enabled_locales' => ['fr', 'en'], 'csrf_protection' => true, 'form' => [ + 'enabled' => true, 'csrf_protection' => [ 'field_name' => '_csrf', ], diff --git a/Tests/DependencyInjection/Fixtures/xml/full.xml b/Tests/DependencyInjection/Fixtures/xml/full.xml index c01e85783..0957d0cff 100644 --- a/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -10,7 +10,7 @@ fr en - + diff --git a/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml b/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml index 20350c9e8..36987869f 100644 --- a/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml +++ b/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml @@ -2,6 +2,7 @@ framework: annotations: false csrf_protection: false form: + enabled: true csrf_protection: true http_method_override: false handle_all_throwables: true diff --git a/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml b/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml index a86432f8d..74ee41091 100644 --- a/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml +++ b/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml @@ -5,5 +5,6 @@ framework: php_errors: log: true form: + enabled: true csrf_protection: enabled: false diff --git a/Tests/DependencyInjection/Fixtures/yml/full.yml b/Tests/DependencyInjection/Fixtures/yml/full.yml index 7550749eb..f70458a6c 100644 --- a/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -4,6 +4,7 @@ framework: enabled_locales: ['fr', 'en'] csrf_protection: true form: + enabled: true csrf_protection: field_name: _csrf http_method_override: false From eca6e49826b24c3f1f62d3ede8638aeb8fb41d81 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Nov 2024 12:59:13 +0100 Subject: [PATCH 166/180] Revert "bug #58937 [FrameworkBundle] Don't auto-register form/csrf when the corresponding components are not installed (nicolas-grekas)" This reverts commit 552f7749d2b66485eb424af656827a0818c5bc4f, reversing changes made to e2f2a967158182109faa233b37f26687f6092a96. --- DependencyInjection/Configuration.php | 6 +----- DependencyInjection/FrameworkExtension.php | 21 +++++++------------ .../Fixtures/php/form_csrf_disabled.php | 1 - .../Fixtures/php/form_no_csrf.php | 1 - .../DependencyInjection/Fixtures/php/full.php | 1 - .../Fixtures/xml/form_csrf_disabled.xml | 2 +- .../Fixtures/xml/form_no_csrf.xml | 2 +- .../DependencyInjection/Fixtures/xml/full.xml | 2 +- .../Fixtures/yml/form_csrf_disabled.yml | 1 - .../Fixtures/yml/form_no_csrf.yml | 1 - .../DependencyInjection/Fixtures/yml/full.yml | 1 - 11 files changed, 12 insertions(+), 27 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 9754cb078..678698f4d 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -237,12 +237,8 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->children() ->arrayNode('form') ->info('Form configuration') - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->addDefaultsIfNotSet() + ->{$enableIfStandalone('symfony/form', Form::class)}() ->children() - ->scalarNode('enabled')->defaultNull()->end() // defaults to !class_exists(FullStack::class) && class_exists(Form::class) ->arrayNode('csrf_protection') ->treatFalseLike(['enabled' => false]) ->treatTrueLike(['enabled' => true]) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 73101912a..3febd6337 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -278,19 +278,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->readConfigEnabled('profiler', $container, $config['profiler']); $this->readConfigEnabled('workflows', $container, $config['workflows']); - // csrf depends on session or stateless token ids being registered - if (null === $config['csrf_protection']['enabled']) { - $this->writeConfigEnabled('csrf_protection', ($config['csrf_protection']['stateless_token_ids'] || $this->readConfigEnabled('session', $container, $config['session'])) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']); - } - - if (null === $config['form']['enabled']) { - $this->writeConfigEnabled('form', !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle']), $config['form']); - } - - if (null === $config['form']['csrf_protection']['enabled']) { - $this->writeConfigEnabled('form.csrf_protection', $config['csrf_protection']['enabled'], $config['form']['csrf_protection']); - } - // A translator must always be registered (as support is included by // default in the Form and Validator component). If disabled, an identity // translator will be used and everything will still work as expected. @@ -479,6 +466,10 @@ public function load(array $configs, ContainerBuilder $container): void $container->removeDefinition('test.session.listener'); } + // csrf depends on session or stateless token ids being registered + if (null === $config['csrf_protection']['enabled']) { + $this->writeConfigEnabled('csrf_protection', ($config['csrf_protection']['stateless_token_ids'] || $this->readConfigEnabled('session', $container, $config['session'])) && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle']), $config['csrf_protection']); + } $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); // form depends on csrf being registered @@ -763,6 +754,10 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont { $loader->load('form.php'); + if (null === $config['form']['csrf_protection']['enabled']) { + $this->writeConfigEnabled('form.csrf_protection', $config['csrf_protection']['enabled'], $config['form']['csrf_protection']); + } + if ($this->readConfigEnabled('form.csrf_protection', $container, $config['form']['csrf_protection'])) { if (!$container->hasDefinition('security.csrf.token_generator')) { throw new \LogicException('To use form CSRF protection, "framework.csrf_protection" must be enabled.'); diff --git a/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php b/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php index 809b40be4..981498609 100644 --- a/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php +++ b/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php @@ -4,7 +4,6 @@ 'annotations' => false, 'csrf_protection' => false, 'form' => [ - 'enabled' => true, 'csrf_protection' => true, ], 'http_method_override' => false, diff --git a/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php b/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php index 5c63ed068..7c052c9ff 100644 --- a/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php +++ b/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php @@ -6,7 +6,6 @@ 'handle_all_throwables' => true, 'php_errors' => ['log' => true], 'form' => [ - 'enabled' => true, 'csrf_protection' => [ 'enabled' => false, ], diff --git a/Tests/DependencyInjection/Fixtures/php/full.php b/Tests/DependencyInjection/Fixtures/php/full.php index a728a4483..0a32ce8b3 100644 --- a/Tests/DependencyInjection/Fixtures/php/full.php +++ b/Tests/DependencyInjection/Fixtures/php/full.php @@ -6,7 +6,6 @@ 'enabled_locales' => ['fr', 'en'], 'csrf_protection' => true, 'form' => [ - 'enabled' => true, 'csrf_protection' => [ 'field_name' => '_csrf', ], diff --git a/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml b/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml index ec97dcdd9..fdd02be87 100644 --- a/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml +++ b/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml @@ -12,7 +12,7 @@ - + diff --git a/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml b/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml index da8ed8b98..de1418108 100644 --- a/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml +++ b/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml @@ -9,7 +9,7 @@ - + diff --git a/Tests/DependencyInjection/Fixtures/xml/full.xml b/Tests/DependencyInjection/Fixtures/xml/full.xml index 0957d0cff..c01e85783 100644 --- a/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -10,7 +10,7 @@ fr en - + diff --git a/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml b/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml index 36987869f..20350c9e8 100644 --- a/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml +++ b/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml @@ -2,7 +2,6 @@ framework: annotations: false csrf_protection: false form: - enabled: true csrf_protection: true http_method_override: false handle_all_throwables: true diff --git a/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml b/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml index 74ee41091..a86432f8d 100644 --- a/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml +++ b/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml @@ -5,6 +5,5 @@ framework: php_errors: log: true form: - enabled: true csrf_protection: enabled: false diff --git a/Tests/DependencyInjection/Fixtures/yml/full.yml b/Tests/DependencyInjection/Fixtures/yml/full.yml index f70458a6c..7550749eb 100644 --- a/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -4,7 +4,6 @@ framework: enabled_locales: ['fr', 'en'] csrf_protection: true form: - enabled: true csrf_protection: field_name: _csrf http_method_override: false From 98aa6623769eab93feca7d976442980f158fd4a8 Mon Sep 17 00:00:00 2001 From: Jonas Elfering Date: Wed, 20 Nov 2024 16:19:47 +0100 Subject: [PATCH 167/180] Revert "[FrameworkBundle] Deprecate making `cache.app` adapter taggable" This reverts commit eed5b284618ec95eedbc376fb140b8fc24619372. --- DependencyInjection/FrameworkExtension.php | 5 ----- .../Fixtures/php/cache_cacheapp_tagaware.php | 16 ---------------- .../Fixtures/xml/cache_cacheapp_tagaware.xml | 15 --------------- .../Fixtures/yml/cache_cacheapp_tagaware.yml | 11 ----------- .../FrameworkExtensionTestCase.php | 13 ------------- 5 files changed, 60 deletions(-) delete mode 100644 Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php delete mode 100644 Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml delete mode 100644 Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index a7749cd30..625158561 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2396,11 +2396,6 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con ]; } foreach ($config['pools'] as $name => $pool) { - if (\in_array('cache.app', $pool['adapters'] ?? [], true) && $pool['tags']) { - trigger_deprecation('symfony/framework-bundle', '7.2', 'Using the "tags" option with the "cache.app" adapter is deprecated. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); - // throw new LogicException('The "tags" option cannot be used with the "cache.app" adapter. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); - } - $pool['adapters'] = $pool['adapters'] ?: ['cache.app']; $isRedisTagAware = ['cache.adapter.redis_tag_aware'] === $pool['adapters']; diff --git a/Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php b/Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php deleted file mode 100644 index 77606f5b1..000000000 --- a/Tests/DependencyInjection/Fixtures/php/cache_cacheapp_tagaware.php +++ /dev/null @@ -1,16 +0,0 @@ -loadFromExtension('framework', [ - 'annotations' => false, - 'http_method_override' => false, - 'handle_all_throwables' => true, - 'php_errors' => ['log' => true], - 'cache' => [ - 'pools' => [ - 'app.tagaware' => [ - 'adapter' => 'cache.app', - 'tags' => true, - ], - ], - ], -]); diff --git a/Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml b/Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml deleted file mode 100644 index 7d59e19d5..000000000 --- a/Tests/DependencyInjection/Fixtures/xml/cache_cacheapp_tagaware.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml b/Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml deleted file mode 100644 index 32ef3d49c..000000000 --- a/Tests/DependencyInjection/Fixtures/yml/cache_cacheapp_tagaware.yml +++ /dev/null @@ -1,11 +0,0 @@ -framework: - annotations: false - http_method_override: false - handle_all_throwables: true - php_errors: - log: true - cache: - pools: - app.tagaware: - adapter: cache.app - tags: true diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 016ae507b..798217191 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; @@ -96,8 +95,6 @@ abstract class FrameworkExtensionTestCase extends TestCase { - use ExpectUserDeprecationMessageTrait; - private static array $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); @@ -1856,16 +1853,6 @@ public function testCacheTaggableTagAppliedToPools() } } - /** - * @group legacy - */ - public function testTaggableCacheAppIsDeprecated() - { - $this->expectUserDeprecationMessage('Since symfony/framework-bundle 7.2: Using the "tags" option with the "cache.app" adapter is deprecated. You can use the "cache.app.taggable" adapter instead (aliased to the TagAwareCacheInterface for autowiring).'); - - $this->createContainerFromFile('cache_cacheapp_tagaware'); - } - /** * @dataProvider appRedisTagAwareConfigProvider */ From 4155d1d9df8f7757304b502a2f0adfbd8fc2ccf3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Dec 2024 11:03:46 +0100 Subject: [PATCH 168/180] [FrameworkBundle] Make uri_signer lazy and improve error when kernel.secret is empty --- DependencyInjection/FrameworkExtension.php | 9 ++++++++- Resources/config/services.php | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 26cae1f30..8e19697f7 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -310,10 +310,17 @@ public function load(array $configs, ContainerBuilder $container): void } } + $emptySecretHint = '"framework.secret" option'; if (isset($config['secret'])) { $container->setParameter('kernel.secret', $config['secret']); + $usedEnvs = []; + $container->resolveEnvPlaceholders($config['secret'], null, $usedEnvs); + + if ($usedEnvs) { + $emptySecretHint = \sprintf('"%s" env var%s', implode('", "', $usedEnvs), 1 === \count($usedEnvs) ? '' : 's'); + } } - $container->parameterCannotBeEmpty('kernel.secret', 'A non-empty value for the parameter "kernel.secret" is required. Did you forget to configure the "framework.secret" option?'); + $container->parameterCannotBeEmpty('kernel.secret', 'A non-empty value for the parameter "kernel.secret" is required. Did you forget to configure the '.$emptySecretHint.'?'); $container->setParameter('kernel.http_method_override', $config['http_method_override']); $container->setParameter('kernel.trust_x_sendfile_type_header', $config['trust_x_sendfile_type_header']); diff --git a/Resources/config/services.php b/Resources/config/services.php index 53856f356..6abe1b6d8 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -157,6 +157,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] ->args([ new Parameter('kernel.secret'), ]) + ->lazy() ->alias(UriSigner::class, 'uri_signer') ->set('config_cache_factory', ResourceCheckerConfigCacheFactory::class) From bda64b23c5a42f5054ae6b619e9bce4a08ca9057 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Thu, 5 Dec 2024 00:17:16 +0100 Subject: [PATCH 169/180] chore: fix CS --- Command/AboutCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Command/AboutCommand.php b/Command/AboutCommand.php index f4281cd21..4dc86130a 100644 --- a/Command/AboutCommand.php +++ b/Command/AboutCommand.php @@ -86,7 +86,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ['Timezone', date_default_timezone_get().' ('.(new \DateTimeImmutable())->format(\DateTimeInterface::W3C).')'], ['OPcache', \extension_loaded('Zend OPcache') ? (filter_var(\ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) ? 'Enabled' : 'Not enabled') : 'Not installed'], ['APCu', \extension_loaded('apcu') ? (filter_var(\ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? 'Enabled' : 'Not enabled') : 'Not installed'], - ['Xdebug', \extension_loaded('xdebug') ? ($xdebugMode && $xdebugMode !== 'off' ? 'Enabled (' . $xdebugMode . ')' : 'Not enabled') : 'Not installed'], + ['Xdebug', \extension_loaded('xdebug') ? ($xdebugMode && 'off' !== $xdebugMode ? 'Enabled (' . $xdebugMode . ')' : 'Not enabled') : 'Not installed'], ]; $io->table([], $rows); From 10ad5ad527e7371d7d3627b6b2e5c96a99ccf6d8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 7 Dec 2024 08:58:47 +0100 Subject: [PATCH 170/180] fix translation lint compatibility with the PseudoLocalizationTranslator --- .../Compiler/TranslationLintCommandPass.php | 33 +++++++++++++++++++ FrameworkBundle.php | 3 ++ 2 files changed, 36 insertions(+) create mode 100644 DependencyInjection/Compiler/TranslationLintCommandPass.php diff --git a/DependencyInjection/Compiler/TranslationLintCommandPass.php b/DependencyInjection/Compiler/TranslationLintCommandPass.php new file mode 100644 index 000000000..4756795d1 --- /dev/null +++ b/DependencyInjection/Compiler/TranslationLintCommandPass.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +final class TranslationLintCommandPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->hasDefinition('console.command.translation_lint') || !$container->has('translator')) { + return; + } + + $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); + + if (!is_subclass_of($translatorClass, TranslatorInterface::class) || !is_subclass_of($translatorClass, TranslatorBagInterface::class)) { + $container->removeDefinition('console.command.translation_lint'); + } + } +} diff --git a/FrameworkBundle.php b/FrameworkBundle.php index a1eb059bb..dc7080892 100644 --- a/FrameworkBundle.php +++ b/FrameworkBundle.php @@ -19,6 +19,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RemoveUnusedSessionMarshallingHandlerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationLintCommandPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\VirtualRequestStackPass; use Symfony\Component\Cache\Adapter\ApcuAdapter; @@ -149,6 +150,8 @@ public function build(ContainerBuilder $container): void $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class); $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING); + // must be registered before the AddConsoleCommandPass + $container->addCompilerPass(new TranslationLintCommandPass(), PassConfig::TYPE_BEFORE_REMOVING, 10); // must be registered as late as possible to get access to all Twig paths registered in // twig.template_iterator definition $this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); From 1c630f4697c9bd87b342e8090cc9022071af4d77 Mon Sep 17 00:00:00 2001 From: raphael-geffroy Date: Sat, 7 Dec 2024 12:21:53 +0100 Subject: [PATCH 171/180] fix: notifier channel bus abstract arg --- DependencyInjection/FrameworkExtension.php | 2 +- Resources/config/notifier.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 9ddf89ac1..a6d595603 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -2784,7 +2784,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ $container->removeDefinition('notifier.channel.email'); } - foreach (['texter', 'chatter', 'notifier.channel.chat', 'notifier.channel.email', 'notifier.channel.sms', 'notifier.channel.push'] as $serviceId) { + foreach (['texter', 'chatter', 'notifier.channel.chat', 'notifier.channel.email', 'notifier.channel.sms', 'notifier.channel.push', 'notifier.channel.desktop'] as $serviceId) { if (!$container->hasDefinition($serviceId)) { continue; } diff --git a/Resources/config/notifier.php b/Resources/config/notifier.php index 71a3cd1fd..28900ad10 100644 --- a/Resources/config/notifier.php +++ b/Resources/config/notifier.php @@ -82,7 +82,10 @@ ->tag('notifier.channel', ['channel' => 'push']) ->set('notifier.channel.desktop', DesktopChannel::class) - ->args([service('texter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) + ->args([ + service('texter.transports'), + abstract_arg('message bus'), + ]) ->tag('notifier.channel', ['channel' => 'desktop']) ->set('notifier.monolog_handler', NotifierHandler::class) From f2c4d746119824062a2252675cacca8b8f0e2e18 Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Sun, 8 Dec 2024 10:46:43 +0100 Subject: [PATCH 172/180] fix(dependency-injection): reset env vars with kernel.reset - fixes #59128 --- Resources/config/services.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/config/services.php b/Resources/config/services.php index c85ccf5d0..a7e1c5198 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -195,6 +195,7 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] tagged_iterator('container.env_var_loader'), ]) ->tag('container.env_var_processor') + ->tag('kernel.reset', ['method' => 'reset']) ->set('slugger', AsciiSlugger::class) ->args([ From 06b9c6f486aa1bc1a1f4b9d00b036f79e3ac3994 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 7 Feb 2025 19:13:17 +0100 Subject: [PATCH 173/180] [Form][FrameworkBundle] Use auto-configuration to make the default CSRF token id apply only to the app; not to bundles --- DependencyInjection/FrameworkExtension.php | 6 ++---- Resources/config/form_csrf.php | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index 556a0cff6..98dd074f4 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -615,7 +615,7 @@ public function load(array $configs, ContainerBuilder $container): void $container->registerForAutoconfiguration(DataCollectorInterface::class) ->addTag('data_collector'); $container->registerForAutoconfiguration(FormTypeInterface::class) - ->addTag('form.type'); + ->addTag('form.type', ['csrf_token_id' => '%.form.type_extension.csrf.token_id%']); $container->registerForAutoconfiguration(FormTypeGuesserInterface::class) ->addTag('form.type_guesser'); $container->registerForAutoconfiguration(FormTypeExtensionInterface::class) @@ -777,9 +777,7 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont $container->setParameter('form.type_extension.csrf.enabled', true); $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']); $container->setParameter('form.type_extension.csrf.field_attr', $config['form']['csrf_protection']['field_attr']); - - $container->getDefinition('form.type_extension.csrf') - ->replaceArgument(7, $config['form']['csrf_protection']['token_id']); + $container->setParameter('.form.type_extension.csrf.token_id', $config['form']['csrf_protection']['token_id']); } else { $container->setParameter('form.type_extension.csrf.enabled', false); } diff --git a/Resources/config/form_csrf.php b/Resources/config/form_csrf.php index c63d087c8..a86bb7c60 100644 --- a/Resources/config/form_csrf.php +++ b/Resources/config/form_csrf.php @@ -24,7 +24,7 @@ param('validator.translation_domain'), service('form.server_params'), param('form.type_extension.csrf.field_attr'), - abstract_arg('framework.form.csrf_protection.token_id'), + param('.form.type_extension.csrf.token_id'), ]) ->tag('form.type_extension') ; From 53cad5c6cfee42bb2c026b907313592ae9eefb8d Mon Sep 17 00:00:00 2001 From: Quentin Schuler Date: Fri, 21 Feb 2025 14:41:03 +0100 Subject: [PATCH 174/180] [FrameworkBundle] Disable the keys normalization of the CSRF form field attributes The form.csrf_protection.field_attr configuration node value should remain as-is when defined. The default behavior of the configuration component is to normalize keys, but in that specific cases, keys becomes HTML attributes and therefore should not be changed. This commit fix that behaviour for the specific node. --- DependencyInjection/Configuration.php | 1 + Tests/DependencyInjection/ConfigurationTest.php | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 678698f4d..4d494eed0 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -250,6 +250,7 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->scalarNode('field_name')->defaultValue('_token')->end() ->arrayNode('field_attr') ->performNoDeepMerging() + ->normalizeKeys(false) ->scalarPrototype()->end() ->defaultValue(['data-controller' => 'csrf-protection']) ->end() diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 53706d2e0..6f3363f39 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -699,6 +699,22 @@ public function testSerializerJsonDetailedErrorMessagesNotSetByDefaultWithDebugD $this->assertSame([], $config['serializer']['default_context'] ?? []); } + public function testFormCsrfProtectionFieldAttrDoNotNormalizeKeys() + { + $processor = new Processor(); + $config = $processor->processConfiguration(new Configuration(false), [ + [ + 'form' => [ + 'csrf_protection' => [ + 'field_attr' => ['data-example-attr' => 'value'], + ], + ], + ], + ]); + + $this->assertSame(['data-example-attr' => 'value'], $config['form']['csrf_protection']['field_attr'] ?? []); + } + protected static function getBundleDefaultConfig() { return [ From c1c6ee8946491b698b067df2258e07918c25da02 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Mon, 24 Mar 2025 05:35:59 +0100 Subject: [PATCH 175/180] [Serializer] Fix ObjectNormalizer default context with named serializers --- DependencyInjection/FrameworkExtension.php | 16 +++------------- Resources/config/serializer.php | 2 +- .../FrameworkExtensionTestCase.php | 16 ++++++++++++---- composer.json | 4 ++-- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index bd27c27a6..8d64adeca 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -1946,24 +1946,14 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->setParameter('serializer.default_context', $defaultContext); } - if (!$container->hasDefinition('serializer.normalizer.object')) { - return; - } - - $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = $arguments[6] ?? $defaultContext; - - if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { - $context += ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; - $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); + if ($config['circular_reference_handler'] ?? false) { + $container->setParameter('.serializer.circular_reference_handler', $config['circular_reference_handler']); } if ($config['max_depth_handler'] ?? false) { - $context += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; + $container->setParameter('.serializer.max_depth_handler', $config['max_depth_handler']); } - $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); - $container->getDefinition('serializer.normalizer.property')->setArgument(5, $defaultContext); $container->setParameter('.serializer.named_serializers', $config['named_serializers'] ?? []); diff --git a/Resources/config/serializer.php b/Resources/config/serializer.php index 4686a88f6..b291f51ac 100644 --- a/Resources/config/serializer.php +++ b/Resources/config/serializer.php @@ -129,7 +129,7 @@ service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, - null, + abstract_arg('default context, set in the SerializerPass'), service('property_info')->ignoreOnInvalid(), ]) ->tag('serializer.normalizer', ['built_in' => true, 'priority' => -1000]) diff --git a/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 5f5f41801..7bf66512d 100644 --- a/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -33,6 +33,7 @@ use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass; @@ -67,6 +68,7 @@ use Symfony\Component\Notifier\TexterInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Security\Core\AuthenticationEvents; +use Symfony\Component\Serializer\DependencyInjection\SerializerPass; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; @@ -1447,9 +1449,6 @@ public function testSerializerEnabled() $this->assertEquals(AttributeLoader::class, $argument[0]->getClass()); $this->assertEquals(new Reference('serializer.name_converter.camel_case_to_snake_case'), $container->getDefinition('serializer.name_converter.metadata_aware')->getArgument(1)); $this->assertEquals(new Reference('property_info', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $container->getDefinition('serializer.normalizer.object')->getArgument(3)); - $this->assertArrayHasKey('circular_reference_handler', $container->getDefinition('serializer.normalizer.object')->getArgument(6)); - $this->assertArrayHasKey('max_depth_handler', $container->getDefinition('serializer.normalizer.object')->getArgument(6)); - $this->assertEquals($container->getDefinition('serializer.normalizer.object')->getArgument(6)['max_depth_handler'], new Reference('my.max.depth.handler')); } public function testSerializerWithoutTranslator() @@ -1547,13 +1546,22 @@ public function testJsonSerializableNormalizerRegistered() public function testObjectNormalizerRegistered() { - $container = $this->createContainerFromFile('full'); + $container = $this->createContainerFromFile('full', compile: false); + $container->addCompilerPass(new SerializerPass()); + $container->addCompilerPass(new ResolveBindingsPass()); + $container->compile(); $definition = $container->getDefinition('serializer.normalizer.object'); $tag = $definition->getTag('serializer.normalizer'); $this->assertEquals(ObjectNormalizer::class, $definition->getClass()); $this->assertEquals(-1000, $tag[0]['priority']); + + $this->assertEquals([ + 'enable_max_depth' => true, + 'circular_reference_handler' => new Reference('my.circular.reference.handler'), + 'max_depth_handler' => new Reference('my.max.depth.handler'), + ], $definition->getArgument(6)); } public function testConstraintViolationListNormalizerRegistered() diff --git a/composer.json b/composer.json index 9b3e7c86e..6689b61b0 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^6.4|^7.0", "symfony/semaphore": "^6.4|^7.0", - "symfony/serializer": "^7.1", + "symfony/serializer": "^7.2.5", "symfony/stopwatch": "^6.4|^7.0", "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", @@ -97,7 +97,7 @@ "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-csrf": "<7.2", "symfony/security-core": "<6.4", - "symfony/serializer": "<7.1", + "symfony/serializer": "<7.2.5", "symfony/stopwatch": "<6.4", "symfony/translation": "<6.4", "symfony/twig-bridge": "<6.4", From e14c287b356b6c30a99fa7862c988e3a4a3ba55d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 6 May 2025 22:43:17 +0200 Subject: [PATCH 176/180] ensure that all supported e-mail validation modes can be configured --- DependencyInjection/Configuration.php | 3 +- .../PhpFrameworkExtensionTest.php | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index cb52a0704..4d44c469f 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -45,6 +45,7 @@ use Symfony\Component\Serializer\Serializer; use Symfony\Component\Translation\Translator; use Symfony\Component\Uid\Factory\UuidFactory; +use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Validation; use Symfony\Component\Webhook\Controller\WebhookController; use Symfony\Component\WebLink\HttpHeaderSerializer; @@ -1066,7 +1067,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->validate()->castToArray()->end() ->end() ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end() + ->enumNode('email_validation_mode')->values(Email::VALIDATION_MODES + ['loose'])->end() ->arrayNode('mapping') ->addDefaultsIfNotSet() ->fixXmlConfig('path') diff --git a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index 53268ffd2..eae457361 100644 --- a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Workflow\Exception\InvalidDefinitionException; class PhpFrameworkExtensionTest extends FrameworkExtensionTestCase @@ -245,4 +246,31 @@ public function testRateLimiterLockFactory() $container->getDefinition('limiter.without_lock')->getArgument(2); } + + /** + * @dataProvider emailValidationModeProvider + */ + public function testValidatorEmailValidationMode(string $mode) + { + $this->expectNotToPerformAssertions(); + + $this->createContainerFromClosure(function (ContainerBuilder $container) use ($mode) { + $container->loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'validation' => [ + 'email_validation_mode' => $mode, + ], + ]); + }); + } + + public function emailValidationModeProvider() + { + foreach (Email::VALIDATION_MODES as $mode) { + yield [$mode]; + } + } } From b238ab0e1ab20793d151def4a4ef1da9d58362aa Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 8 May 2025 00:10:13 +0900 Subject: [PATCH 177/180] [FrameworkBundle] Ensure `Email` class exists before using it --- DependencyInjection/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 4d44c469f..bae8967a8 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1067,7 +1067,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->validate()->castToArray()->end() ->end() ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(Email::VALIDATION_MODES + ['loose'])->end() + ->enumNode('email_validation_mode')->values((class_exists(Email::class) ? Email::VALIDATION_MODES : ['html5-allow-no-tld', 'html5', 'strict']) + ['loose'])->end() ->arrayNode('mapping') ->addDefaultsIfNotSet() ->fixXmlConfig('path') From b63dec25c8bb03e14e84fa878e306b44eb8810c9 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 8 May 2025 15:32:34 +0200 Subject: [PATCH 178/180] make data provider static --- Tests/DependencyInjection/PhpFrameworkExtensionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index eae457361..e5cc8522a 100644 --- a/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -267,7 +267,7 @@ public function testValidatorEmailValidationMode(string $mode) }); } - public function emailValidationModeProvider() + public static function emailValidationModeProvider() { foreach (Email::VALIDATION_MODES as $mode) { yield [$mode]; From 42cca5c8fb95d851bf3fb709217e8feb62a4376a Mon Sep 17 00:00:00 2001 From: Nowfel2501 Date: Fri, 9 May 2025 21:12:33 +0200 Subject: [PATCH 179/180] Improve readability of disallow_search_engine_index condition --- DependencyInjection/FrameworkExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/FrameworkExtension.php b/DependencyInjection/FrameworkExtension.php index f585b5bbb..68386120e 100644 --- a/DependencyInjection/FrameworkExtension.php +++ b/DependencyInjection/FrameworkExtension.php @@ -735,7 +735,7 @@ static function (ChildDefinition $definition, AsPeriodicTask|AsCronTask $attribu $container->getDefinition('config_cache_factory')->setArguments([]); } - if (!$config['disallow_search_engine_index'] ?? false) { + if (!$config['disallow_search_engine_index']) { $container->removeDefinition('disallow_search_engine_index_response_listener'); } From b1de19b2083484d0ce945977f6c6484e9e493a2e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 14 May 2025 09:14:36 +0200 Subject: [PATCH 180/180] remove no longer used service definition --- Resources/config/mailer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/config/mailer.php b/Resources/config/mailer.php index 7a3a95739..f1dc560ab 100644 --- a/Resources/config/mailer.php +++ b/Resources/config/mailer.php @@ -45,7 +45,6 @@ tagged_iterator('mailer.transport_factory'), ]) - ->set('mailer.default_transport', TransportInterface::class) ->alias('mailer.default_transport', 'mailer.transports') ->alias(TransportInterface::class, 'mailer.default_transport')