1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Console\Command;
13
14use Symfony\Component\Console\Exception\LogicException;
15use Symfony\Component\Lock\LockFactory;
16use Symfony\Component\Lock\LockInterface;
17use Symfony\Component\Lock\Store\FlockStore;
18use Symfony\Component\Lock\Store\SemaphoreStore;
19
20/**
21 * Basic lock feature for commands.
22 *
23 * @author Geoffrey Brier <geoffrey.brier@gmail.com>
24 */
25trait LockableTrait
26{
27    /** @var LockInterface|null */
28    private $lock;
29
30    /**
31     * Locks a command.
32     */
33    private function lock(string $name = null, bool $blocking = false): bool
34    {
35        if (!class_exists(SemaphoreStore::class)) {
36            throw new LogicException('To enable the locking feature you must install the symfony/lock component.');
37        }
38
39        if (null !== $this->lock) {
40            throw new LogicException('A lock is already in place.');
41        }
42
43        if (SemaphoreStore::isSupported()) {
44            $store = new SemaphoreStore();
45        } else {
46            $store = new FlockStore();
47        }
48
49        $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName());
50        if (!$this->lock->acquire($blocking)) {
51            $this->lock = null;
52
53            return false;
54        }
55
56        return true;
57    }
58
59    /**
60     * Releases the command lock if there is one.
61     */
62    private function release()
63    {
64        if ($this->lock) {
65            $this->lock->release();
66            $this->lock = null;
67        }
68    }
69}
70