diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index f5f05ff362708..7b5bbaeda8e29 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/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/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 75cfe1d1f0d84..5b644c7407c0a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/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/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/lock_service.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/lock_service.php new file mode 100644 index 0000000000000..b3a17ee43dc39 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/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/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/semaphore_service.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/semaphore_service.php new file mode 100644 index 0000000000000..e94d809bebeff --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/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/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_service.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_service.xml new file mode 100644 index 0000000000000..d184cc2f7a744 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_service.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + my_service + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml new file mode 100644 index 0000000000000..4939a3300624e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/semaphore_service.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + my_service + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_service.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_service.yml new file mode 100644 index 0000000000000..4cea81ea0ef82 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/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/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore_service.yml new file mode 100644 index 0000000000000..f966965b56c66 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/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/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index a381e14720755..b4d7af1042c64 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/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([