diff --git a/src/Symfony/Component/Console/Command/LockableTrait.php b/src/Symfony/Component/Console/Command/LockableTrait.php index cd7548f02f9e9..f0001cc52d772 100644 --- a/src/Symfony/Component/Console/Command/LockableTrait.php +++ b/src/Symfony/Component/Console/Command/LockableTrait.php @@ -26,6 +26,8 @@ trait LockableTrait { private ?LockInterface $lock = null; + private ?LockFactory $lockFactory = null; + /** * Locks a command. */ @@ -39,13 +41,17 @@ private function lock(?string $name = null, bool $blocking = false): bool throw new LogicException('A lock is already in place.'); } - if (SemaphoreStore::isSupported()) { - $store = new SemaphoreStore(); - } else { - $store = new FlockStore(); + if (null === $this->lockFactory) { + if (SemaphoreStore::isSupported()) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $this->lockFactory = (new LockFactory($store)); } - $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); + $this->lock = $this->lockFactory->createLock($name ?: $this->getName()); if (!$this->lock->acquire($blocking)) { $this->lock = null; diff --git a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php index 77b54f9ee369b..0268d9681e5c5 100644 --- a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php +++ b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\SharedLockInterface; use Symfony\Component\Lock\Store\FlockStore; use Symfony\Component\Lock\Store\SemaphoreStore; @@ -26,6 +27,7 @@ public static function setUpBeforeClass(): void self::$fixturesPath = __DIR__.'/../Fixtures/'; require_once self::$fixturesPath.'/FooLockCommand.php'; require_once self::$fixturesPath.'/FooLock2Command.php'; + require_once self::$fixturesPath.'/FooLock3Command.php'; } public function testLockIsReleased() @@ -64,4 +66,18 @@ public function testMultipleLockCallsThrowLogicException() $tester = new CommandTester($command); $this->assertSame(1, $tester->execute([])); } + + public function testCustomLockFactoryIsUsed() + { + $lockFactory = $this->createMock(LockFactory::class); + $command = new \FooLock3Command($lockFactory); + + $tester = new CommandTester($command); + + $lock = $this->createMock(SharedLockInterface::class); + $lock->method('acquire')->willReturn(false); + + $lockFactory->expects(static::once())->method('createLock')->willReturn($lock); + $this->assertSame(1, $tester->execute([])); + } } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/FooLock3Command.php b/src/Symfony/Component/Console/Tests/Fixtures/FooLock3Command.php new file mode 100644 index 0000000000000..78492de6950a8 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/FooLock3Command.php @@ -0,0 +1,35 @@ +lockFactory = $lockFactory; + } + + protected function configure(): void + { + $this->setName('foo:lock3'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (!$this->lock()) { + return 1; + } + + $this->release(); + + return 2; + } +}