Passed
Push — master ( f3f932...d66714 )
by Никита
02:09
created

FileMutex::get_delete_on_release()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
    namespace NokitaKaze\Mutex;
4
5
    class FileMutex implements MutexInterface {
6
        /**
7
         * @var string Название файла, на котором будет работать мьютекс
8
         */
9
        var $filename = '';
10
        protected $_mutex_type;
11
        /**
12
         * @var string|null Название мьютекса, должно состоять из валидных для имени файлов символов
13
         */
14
        var $_mutex_name;
15
        /**
16
         * @var string|null Место, где расположен файл.
17
         * Не используется в логике класса
18
         */
19
        protected $_mutex_folder;
20
        /**
21
         * @var double|null Время, когда мьютекс был получен
22
         */
23
        protected $_lock_acquired_time = null;
24
        /**
25
         * @var boolean Текущее состояние мьютекса
26
         */
27
        protected $_lock_acquired = false;
28
        /**
29
         * @var resource|false Файл, открывающийся через fopen
30
         */
31
        protected $_file_handler = false;
32
        /**
33
         * @var boolean Удалять файл при анлоке
34
         * В данный момент это unsafe поведение, из-за немандаторного доступа к файлам из PHP
35
         */
36
        protected $_delete_on_release = false;
37
38
        /**
39
         * @param MutexSettings|array $settings
40
         */
41 4
        function __construct($settings) {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
42
            /**
43
             * @var MutexSettings $settings
44
             */
45 4
            $settings = (object) $settings;
46 4
            if (!isset($settings->type)) {
1 ignored issue
show
Bug introduced by
Accessing type on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
47
                $settings->type = null;
1 ignored issue
show
Bug introduced by
Accessing type on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
48
            }
49 4
            if (!isset($settings->folder)) {
1 ignored issue
show
Bug introduced by
Accessing folder on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
50 1
                $settings->folder = null;
1 ignored issue
show
Bug introduced by
Accessing folder on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
51 1
            }
52
53 4
            $this->_mutex_type = is_null($settings->type) ? self::SERVER : $settings->type;
1 ignored issue
show
Bug introduced by
Accessing type on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
54 4
            $this->_mutex_folder = is_null($settings->folder) ? sys_get_temp_dir() : $settings->folder;
1 ignored issue
show
Bug introduced by
Accessing folder on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
55 4
            $this->_mutex_name = $settings->name;
1 ignored issue
show
Bug introduced by
Accessing name on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
56 4
            if (isset($settings->delete_on_release)) {
1 ignored issue
show
Bug introduced by
Accessing delete_on_release on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
57
                $this->_delete_on_release = $settings->delete_on_release;
1 ignored issue
show
Bug introduced by
Accessing delete_on_release on the interface NokitaKaze\Mutex\MutexSettings suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
58
            }
59
60 4
            $prefix = '';
61 4
            if ($this->_mutex_type == self::SERVER) {
62 4
                $prefix = hash('sha512', self::getDomainString()).'_';
63 4
            } elseif ($this->_mutex_type == self::DIRECTORY) {
64 1
                $prefix = hash('sha512', strtolower(self::getDirectoryString())).'_';
65 1
            }
66 4
            $this->filename = $this->_mutex_folder.DIRECTORY_SEPARATOR.'smartmutex_'.$prefix.$this->_mutex_name.'.lock';
67 4
        }
68
69 4
        function __destruct() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
70 4
            $this->release_lock();
71 4
        }
72
73
        /**
74
         * @return string
75
         */
76 6
        static function getDomainString() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
77 6
            if (isset($_SERVER['HTTP_HOST']) and ($_SERVER['HTTP_HOST'] != '')) {
78 1
                return $_SERVER['HTTP_HOST'];
79 6
            } elseif (isset($_SERVER['HOSTNAME']) and ($_SERVER['HOSTNAME'] != '')) {
80 1
                return $_SERVER['HOSTNAME'];
81 6
            } elseif (isset($_SERVER['SCRIPT_NAME'])) {
82 5
                return $_SERVER['SCRIPT_NAME'];
83
            } else {
84 2
                return 'none';
85
            }
86
        }
87
88
        /**
89
         * @return string
90
         */
91 2
        static function getDirectoryString() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
92 2
            if (isset($_SERVER['DOCUMENT_ROOT']) and ($_SERVER['DOCUMENT_ROOT'] != '')) {
93 1
                return $_SERVER['DOCUMENT_ROOT'];
94 2
            } elseif (isset($_SERVER['PWD']) and ($_SERVER['PWD'] != '')) {
95 2
                return $_SERVER['PWD'];
96 1
            } elseif (isset($_SERVER['SCRIPT_NAME'])) {
97 1
                return $_SERVER['SCRIPT_NAME'];
98
            } else {
99 1
                return 'none';
100
            }
101
        }
102
103
        /**
104
         * @return boolean
105
         *
106
         * @throws MutexException
107
         */
108 1
        function is_free() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
109 1
            if ($this->_lock_acquired) {
110 1
                return false;
111
            }
112 1
            if (!file_exists(dirname($this->filename))) {
113 1
                throw new MutexException('Folder "'.dirname($this->filename).'" does not exist', 1);
114 1
            } elseif (!is_dir(dirname($this->filename))) {
115 1
                throw new MutexException('Folder "'.dirname($this->filename).'" does not exist', 4);
116 1
            } elseif (!is_writable(dirname($this->filename))) {
117 1
                throw new MutexException('Folder "'.dirname($this->filename).'" is not writable', 2);
118 1
            } elseif (file_exists($this->filename) and !is_writable($this->filename)) {
119 1
                throw new MutexException('File "'.$this->filename.'" is not writable', 3);
120
            }
121
122 1
            $fo = fopen($this->filename, 'ab');
123 1
            $result = flock($fo, LOCK_EX | LOCK_NB);
124 1
            flock($fo, LOCK_UN);
125 1
            fclose($fo);
126
127 1
            return $result;
128
        }
129
130
        /**
131
         * @param double|integer $time
132
         *
133
         * @return bool
134
         * @throws MutexException
135
         */
136 3
        function get_lock($time = -1) {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
137 3
            $tmp_time = microtime(true);
138 3
            if ($this->_lock_acquired) {
139 2
                return true;
140
            }
141
142 3
            if (!file_exists(dirname($this->filename))) {
143 1
                throw new MutexException('Folder "'.dirname($this->filename).'" does not exist', 1);
144 3
            } elseif (!is_dir(dirname($this->filename))) {
145 1
                throw new MutexException('Folder "'.dirname($this->filename).'" is not a folder', 4);
146 3
            } elseif (!is_writable(dirname($this->filename))) {
147 1
                throw new MutexException('Folder "'.dirname($this->filename).'" is not writable', 2);
148 3
            } elseif (file_exists($this->filename) and !is_writable($this->filename)) {
149 1
                throw new MutexException('File "'.$this->filename.'" is not writable', 3);
150
            }
151
152
            // Открываем файл
153 3
            $this->_file_handler = fopen($this->filename, file_exists($this->filename) ? 'ab' : 'wb');
154 3
            while (($this->_file_handler === false) and (
155
                    ($tmp_time + $time >= microtime(true)) or ($time == -1)
156 3
                )) {
157
                usleep(10000);
158
                $this->_file_handler = fopen($this->filename, 'ab');
159
            }
160 3
            if ($this->_file_handler === false) {
161
                return false;
162
            }
163
164
            // Блочим файл
165 3
            if ($time >= 0) {
166 3
                $result = flock($this->_file_handler, LOCK_EX | LOCK_NB);
167 3
                while (!$result and ($tmp_time + $time >= microtime(true))) {
168
                    // U MAD?
169 1
                    usleep(10000);
170 1
                    $result = flock($this->_file_handler, LOCK_EX | LOCK_NB);
171 1
                }
172 3
            } else {
173
                $result = flock($this->_file_handler, LOCK_EX);
174
            }
175
176 3
            if ($result) {
177 3
                $this->_lock_acquired_time = microtime(true);
178
                // @todo Не работает под Windows
179 3
                fwrite($this->_file_handler, posix_getpid()."\n".microtime(true)."\n".posix_getuid()."\n\n");
180 3
                fflush($this->_file_handler);
181 3
                $this->_lock_acquired = true;
182 3
            } else {
183 1
                fclose($this->_file_handler);
184 1
                $this->_file_handler = false;
185
            }
186
187 3
            return $result;
188
        }
189
190 4
        function release_lock() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
191 4
            if (!$this->_lock_acquired) {
192 4
                return;
193
            }
194 3
            if (is_resource($this->_file_handler)) {// @hint По неизвестным причинам это не always true condition
195 3
                flock($this->_file_handler, LOCK_UN);
196 3
                fclose($this->_file_handler);
197 3
            }
198 3
            $this->_file_handler = false;
199 3
            $this->_lock_acquired = false;
200 3
            $this->_lock_acquired_time = null;
201
202 3
            if ($this->_delete_on_release and file_exists($this->filename)) {
203 1
                @unlink($this->filename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
204 1
            }
205 3
        }
206
207
        /**
208
         * @return double|null
209
         */
210 1
        function get_acquired_time() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
211 1
            return $this->_lock_acquired_time;
212
        }
213
214
        /**
215
         * @return string
216
         */
217 1
        function get_mutex_name() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
218 1
            return $this->_mutex_name;
219
        }
220
221
        /**
222
         * @return boolean
223
         */
224 1
        function get_delete_on_release() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
225 1
            return $this->_delete_on_release;
226
        }
227
228
        /**
229
         * @return boolean
230
         */
231 3
        function is_acquired() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
232 3
            return $this->_lock_acquired;
233
        }
234
    }
235
236
?>
1 ignored issue
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...