Lock::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 4
crap 1
1
<?php
2
3
namespace Hgraca\Lock;
4
5
use Exception;
6
use Hgraca\Lock\Adapter\FileSystem\FileSystemAdapter;
7
use Hgraca\Lock\Exception\CouldNotCreateLockException;
8
use Hgraca\Lock\Exception\CouldNotReleaseLockException;
9
use Hgraca\Lock\Exception\LockNotFoundException;
10
use Hgraca\Lock\Port\FileSystem\Exception\InvalidPathException;
11
use Hgraca\Lock\Port\FileSystem\Exception\PathAlreadyExistsException;
12
use Hgraca\Lock\Port\FileSystem\FileSystemInterface;
13
14
final class Lock
15
{
16
    /** @var string */
17
    private $lockPath;
18
19
    /** @var string */
20
    private $lockName;
21
22
    /** @var string */
23
    private $lockExt;
24
25
    /** @var FileSystemInterface */
26
    private $fileSystem;
27
28 9
    public function __construct(
29
        string $lockName = 'default',
30
        string $lockPath = null,
31
        string $lockExt = 'lock',
32
        FileSystemInterface $fileSystem = null
33
    ) {
34 9
        $this->lockName = $lockName;
35 9
        $this->lockPath = $lockPath ?? sys_get_temp_dir();
36 9
        $this->lockExt = $lockExt;
37 9
        $this->fileSystem = $fileSystem ?? new FileSystemAdapter();
38 9
    }
39
40 7
    public function acquire(): bool
41
    {
42 7
        if ($this->lockExists()) {
43 2
            return $this->isMine();
44
        }
45
46 5
        return $this->createLock();
47
    }
48
49
    /**
50
     * @throws CouldNotReleaseLockException
51
     * @throws InvalidPathException
52
     */
53 3
    public function release(): bool
54
    {
55 3
        if ($this->lockExists()) {
56 2
            $this->fileSystem->deleteFile($this->getLockFilePath());
57
        }
58
59 3
        if ($this->lockExists()) {
60 1
            throw new CouldNotReleaseLockException();
61
        }
62
63 2
        return true;
64
    }
65
66
    /**
67
     * @throws CouldNotCreateLockException
68
     * @throws InvalidPathException
69
     * @throws PathAlreadyExistsException
70
     */
71 5
    private function createLock(string $myPid = null): bool
72
    {
73 5
        $this->fileSystem->createDir($this->lockPath);
74
75 5
        $this->fileSystem->writeFile($this->getLockFilePath(), $myPid ?? getmypid());
76
77 5
        if (!$this->lockExists()) {
78 1
            throw new CouldNotCreateLockException();
79
        }
80
81 4
        if (!$this->isMine()) {
82 1
            throw new CouldNotCreateLockException('Another process somehow locked before us!');
83
        }
84
85 2
        return true;
86
    }
87
88 9
    private function getLockFilePath(): string
89
    {
90
        return
91 9
            rtrim($this->lockPath, '/')
92 9
            . '/'
93 9
            . rtrim(ltrim($this->lockName, '/'), '.')
94 9
            . '.'
95 9
            . ltrim($this->lockExt, '.');
96
    }
97
98 9
    private function lockExists(): bool
99
    {
100 9
        return $this->fileSystem->fileExists($this->getLockFilePath());
101
    }
102
103 6
    private function isMine(): bool
104
    {
105 6
        return getmypid() === $this->getLockPid();
106
    }
107
108
    /**
109
     * @throws LockNotFoundException
110
     */
111 6
    private function getLockPid(): int
112
    {
113
        try {
114 6
            return $this->fileSystem->readFile($this->getLockFilePath());
115 1
        } catch (Exception $e) {
116 1
            throw new LockNotFoundException('', 0, $e);
117
        }
118
    }
119
}
120