Passed
Branch master (776013)
by payever
03:51
created

FileLock::lock()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * PHP version 5.4 and 7
4
 *
5
 * @package   Payever\Core
6
 * @author    Hennadii.Shymanskyi <[email protected]>
7
 * @copyright 2017-2019 payever GmbH
8
 * @license   MIT <https://opensource.org/licenses/MIT>
9
 */
10
11
namespace Payever\ExternalIntegration\Core\Lock;
12
13
/**
14
 * PHP version 5.4 and 7
15
 *
16
 * @package   Payever\Core
17
 * @author    Hennadii.Shymanskyi <[email protected]>
18
 * @copyright 2017-2019 payever GmbH
19
 * @license   MIT <https://opensource.org/licenses/MIT>
20
 */
21
class FileLock implements LockInterface
22
{
23
    const SLEEP_SECONDS = 1;
24
25
    /** @var string */
26
    private $directory;
27
28
    /**
29
     * FileLock constructor.
30
     *
31
     * @param string $directory
32
     */
33
    public function __construct($directory)
34
    {
35
        if (!is_writable($directory)) {
36
            throw new \UnexpectedValueException(sprintf('Directory %s is not writable', $directory));
37
        }
38
39
        $this->directory = $directory;
40
    }
41
42
    /**
43
     * @inheritdoc
44
     */
45
    public function acquireLock($lockName, $timeout)
46
    {
47
        $filename = $this->getLockFileName($lockName);
48
49
        $this->waitForUnlock($filename, $timeout);
50
51
        $this->releaseLock($lockName);
52
53
        $this->lock($filename);
54
    }
55
56
    /**
57
     * @inheritdoc
58
     */
59
    public function releaseLock($lockName)
60
    {
61
        $filename = $this->getLockFileName($lockName);
62
63
        $this->unlock($filename);
64
    }
65
66
    /**
67
     * @param string $name
68
     *
69
     * @return string
70
     */
71
    private function getLockFileName($name)
72
    {
73
        return $this->directory . DIRECTORY_SEPARATOR . $name . ".lock";
74
    }
75
76
    /**
77
     * @param string $filename
78
     */
79
    private function lock($filename)
80
    {
81
        $handle = fopen($filename, "w");
82
        fclose($handle);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
        fclose(/** @scrutinizer ignore-type */ $handle);
Loading history...
83
    }
84
85
    /**
86
     * @param string $filename
87
     */
88
    private function unlock($filename)
89
    {
90
        if (file_exists($filename)) {
91
            unlink($filename);
92
        }
93
    }
94
95
    /**
96
     * @param string $filename
97
     * @param int $timeout
98
     */
99
    private function waitForUnlock($filename, $timeout)
100
    {
101
        if (file_exists($filename)) {
102
            $maxTimestamp = filectime($filename) + $timeout;
103
            while (file_exists($filename) && time() < $maxTimestamp) {
104
                sleep(self::SLEEP_SECONDS);
105
            }
106
        }
107
    }
108
}
109