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([