Lock   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 5
dl 0
loc 106
ccs 38
cts 38
cp 1
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A acquire() 0 8 2
A release() 0 12 3
A createLock() 0 16 3
A getLockFilePath() 0 9 1
A lockExists() 0 4 1
A isMine() 0 4 1
A getLockPid() 0 8 2
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