Completed
Push — developer ( dc3c7c...6e5def )
by Никита
15:38
created

SmallFilesQueueTransport::__construct()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5.3906

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 12
cts 16
cp 0.75
rs 8.8571
cc 5
eloc 14
nc 6
nop 1
crap 5.3906
1
<?php
2
3
    namespace NokitaKaze\Queue;
4
5
    use NokitaKaze\Mutex\FileMutex;
6
7
    class SmallFilesQueueTransport extends AbstractQueueTransport {
8
        const SINGLE_FILE_DB_VERSION = 1;
9
10
        protected $_message_folder;
11
        protected $_queue_name;
12
        protected $_message_folder_subfolder_count = Queue::DefaultMessageFolderSubfolderCount;
13
        protected $_key_to_file = [];
14
        protected $_is_inotify_enabled;
15
        protected $_chunk_file_postfix = '';
16
17
        /**
18
         * @var iMessage[]
19
         */
20
        protected $_last_consumed_messages = [];
21
        /**
22
         * @var integer[] В keys список файлов, которые были прочитаны
23
         */
24
        protected $_consumed_filenames = [];
25
26
        /**
27
         * @param SmallFilesQueueConstructionSettings|object $settings
28
         *
29
         * @throws QueueException
30
         */
31 45
        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...
32 45
            if (!isset($settings->message_folder)) {
33 3
                throw new QueueException('message_folder has not been set');
34
            }
35 42
            if (!isset($settings->name)) {
36 3
                throw new QueueException('name has not been set');
37
            }
38 39
            $this->_message_folder = $settings->message_folder;
39 39
            $this->_queue_name = $settings->name;
40 39
            if (isset($settings->message_folder_subfolder_count)) {
41
                $this->_message_folder_subfolder_count = $settings->message_folder_subfolder_count;
42
            }
43 39
            if (isset($settings->is_inotify_enabled)) {
44
                $this->_is_inotify_enabled = $settings->is_inotify_enabled;
45
            } else {
46 39
                $this->_is_inotify_enabled = function_exists('inotify_init');
47
            }
48 39
            $this->_chunk_file_postfix = '_'.static::generate_rnd_postfix();
49 39
        }
50
51
        /**
52
         * @param boolean $mode
53
         *
54
         * @hint Ничего не делаем, у этого транспорта нет эксклюзивного режима
55
         * @codeCoverageIgnore
56
         */
57
        function set_exclusive_mode($mode) { }
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...
58
59
        /**
60
         * @return string
61
         */
62 2511
        function get_queue_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...
63 2511
            return $this->_queue_name;
64
        }
65
66 2502
        function save() {
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...
67 2502
            $this->set_same_time_flag(1);
68 2502
            if (empty($this->_pushed_for_save)) {
69 12
                return;
70
            }
71
72
            /**
73
             * @var SmallFilesQueueSingleFile $data
74
             */
75 2502
            $data = (object) [];
76 2502
            $data->queue = $this->_pushed_for_save;
0 ignored issues
show
Bug introduced by
Accessing queue on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
77 2502
            $data->queue_name = $this->_queue_name;
0 ignored issues
show
Bug introduced by
Accessing queue_name on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
78 2502
            $data->time_create = microtime(true);
0 ignored issues
show
Bug introduced by
Accessing time_create on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
79 2502
            $data->time_last_update = microtime(true);
0 ignored issues
show
Bug introduced by
Accessing time_last_update on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
80 2502
            $data->version = self::SINGLE_FILE_DB_VERSION;
0 ignored issues
show
Bug introduced by
Accessing version on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
81 2502
            $num = mt_rand(0, $this->_message_folder_subfolder_count - 1);
82 2502
            $folder = $this->_message_folder.'/'.$num;
83 2502
            FileMutex::create_folders_in_path($folder);
84 2502
            $filename = sprintf('%s/smartqueue_%s%s.chunk.dat',
85 2502
                $folder, number_format(microtime(true), 4, '.', ''), $this->_chunk_file_postfix);
86
87 2502
            $u = file_put_contents($filename, serialize($data), LOCK_EX);
88 2502
            if ($u === false) {
89
                // @codeCoverageIgnoreStart
90
                throw new QueueException('Can not save queue to a file');
91
                // @codeCoverageIgnoreEnd
92
            }
93 2502
            foreach ($this->_pushed_for_save as $message) {
94 2502
                $this->_key_to_file[static::get_real_key_for_message($message)] = $filename;
95 834
            }
96 2502
            $this->_pushed_for_save = [];
97 2502
        }
98
99
        /**
100
         * @param double|integer $wait_time
101
         *
102
         * @return iMessage|object|null
103
         * @throws QueueException
104
         */
105 2511
        function consume_next_message($wait_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...
106 2511
            $this->set_same_time_flag(2);
107 2511
            if (!empty($this->_last_consumed_messages)) {
108 1902
                return array_shift($this->_last_consumed_messages);
109
            }
110
111 2511
            return $this->consume_next_message_without_inotify($wait_time);
112
            /*
113
            if ($this->_is_inotify_enabled and false) {// @todo добавить Inotify
114
                // @codeCoverageIgnoreStart
115
                return $this->consume_next_message_with_inotify($wait_time);
116
                // @codeCoverageIgnoreEnd
117
            } else {
118
                return $this->consume_next_message_without_inotify($wait_time);
119
            }
120
            */
121
        }
122
123 6
        function clear_consumed_keys() {
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...
124 6
            parent::clear_consumed_keys();
125 6
            $this->_last_consumed_messages = [];
126 6
            $this->_consumed_filenames = [];
127 6
        }
128
129 2535
        function __clone() {
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...
130 2535
            parent::__clone();
131 2535
            foreach ($this->_last_consumed_messages as &$message) {
132
                $message = clone $message;
133 845
            }
134 2535
        }
135
136
        /**
137
         * @param double|integer $wait_time
138
         *
139
         * @return iMessage|object|null
140
         * @throws QueueException
141
         */
142 2511
        protected function consume_next_message_without_inotify($wait_time = -1) {
143 2511
            $start = microtime(true);
144
            do {
145 2511
                for ($i = 0; $i < $this->_message_folder_subfolder_count; $i++) {
146 2511
                    $folder = $this->_message_folder.'/'.$i;
147 2511
                    if (!file_exists($folder) or !is_readable($folder) or !is_dir($folder)) {
148 2468
                        continue;
149
                    }
150 2502
                    $event = $this->consume_next_message_without_inotify_folder($folder);
151 2502
                    if (!is_null($event)) {
152 2502
                        return $event;
153
                    }
154 829
                }
155 2490
            } while (($wait_time == -1) or ($start + $wait_time >= microtime(true)));
156
157 2490
            return null;
158
        }
159
160
        /**
161
         * @param string $folder
162
         *
163
         * @return iMessage|object|null
164
         */
165 2502
        protected function consume_next_message_without_inotify_folder($folder) {
166 2502
            foreach (scandir($folder) as $f) {
167 2502
                if (in_array($f, ['.', '..']) or !preg_match('|smartqueue_[0-9.]+(_[a-z0-9]+)?\\.chunk\\.dat$|', $f)) {
168 2502
                    continue;
169
                }
170 2502
                $filename = $folder.'/'.$f;
171 2502
                if (is_dir($filename) or !is_readable($filename)) {
172
                    continue;
173
                }
174 2502
                $event = $this->consume_next_message_from_file($filename);
175 2502
                if (!is_null($event)) {
176 2502
                    return $event;
177
                }
178 829
            }
179
180 2487
            return null;
181
        }
182
183
184
        /**
185
         * Забираем новые event'ы из файла. Файл должен быть уже существующим, читабельным
186
         *
187
         * Проверка на присутствие в индексе осуществляется в этом файле
188
         *
189
         * @param string $filename
190
         *
191
         * @return iMessage|object|null
192
         */
193 2502
        protected function consume_next_message_from_file($filename) {
194 2502
            if (isset($this->_consumed_filenames[$filename])) {
195 2487
                return null;
196
            }
197
198 2502
            $fi = fopen($filename, 'r');
199 2502
            $locked = flock($fi, LOCK_EX | LOCK_NB);
200 2502
            if (!$locked) {
201
                fclose($fi);
202
203
                return null;
204
            }
205
206 2502
            $buf = file_get_contents($filename);
207
            /**
208
             * @var SmallFilesQueueSingleFile $file_data
209
             */
210 2502
            $file_data = @unserialize($buf);
211 2502
            if (!is_object($file_data)) {
212
                // File does not contain Single Queue object
213
                flock($fi, LOCK_UN);
214
                fclose($fi);
215
216
                return null;
217
            }
218 2502
            if ($file_data->queue_name != $this->get_queue_name()) {
219 6
                flock($fi, LOCK_UN);
220 6
                fclose($fi);
221
222 6
                return null;
223
            }
224 2502
            if ($file_data->version != self::SINGLE_FILE_DB_VERSION) {
225
                flock($fi, LOCK_UN);
226
                fclose($fi);
227
228
                return null;
229
            }
230
231 2502
            $this->_last_consumed_messages = [];
232 2502
            foreach ($file_data->queue as $message) {
233 2502
                $key = self::get_real_key_for_message($message);
234 2502
                if (isset($this->_consumed_keys[$key])) {
235 6
                    continue;
236
                }
237
238 2502
                $message->time_consumed = microtime(true);
239 2502
                $message->queue = $this;
240 2502
                $this->_key_to_file[$key] = $filename;
241 2502
                $this->_last_consumed_messages[] = $message;
242 2502
                $this->_consumed_keys[$key] = 1;
243 834
            }
244 2502
            flock($fi, LOCK_UN);
245 2502
            fclose($fi);
246 2502
            $this->_consumed_filenames[$filename] = 1;
247
248 2502
            return !empty($this->_last_consumed_messages) ? array_shift($this->_last_consumed_messages) : null;
249
        }
250
251
        /**
252
         * @param iMessage[]|object[] $messages
253
         */
254 2352
        protected function copy_key_to_file_from_messages(array $messages) {
255 2352
            foreach ($messages as $message) {
256 2352
                if (isset($message->queue) and (get_class($message->queue) == self::class)) {
257 2352
                    foreach ($message->queue->_key_to_file as $key => $filename) {
258 2352
                        $this->_key_to_file[$key] = $filename;
259 784
                    }
260 784
                }
261 784
            }
262 2352
        }
263
264
        /**
265
         * @param iMessage[]|object[] $messages
266
         *
267
         * @return array[]
268
         */
269 2352
        protected function get_filenames_from_messages(array $messages) {
270 2352
            $this->copy_key_to_file_from_messages($messages);
271 2352
            $filenames = [];
272 2352
            $filenames_contains_keys = [];
273 2352
            foreach ($messages as $message) {
274 2352
                $key = self::get_real_key_for_message($message);
275 2352
                if (!isset($this->_key_to_file[$key])) {
276 2202
                    continue;
277
                }
278 2352
                $filename = $this->_key_to_file[$key];
279 2352
                $filenames[] = $filename;
280 2352
                if (!isset($filenames_contains_keys[$filename])) {
281 2352
                    $filenames_contains_keys[$filename] = [];
282 784
                }
283
284 2352
                $filenames_contains_keys[$filename][] = $key;
285 784
            }
286
287 2352
            return [$filenames, $filenames_contains_keys];
288
        }
289
290
        /**
291
         * Удалить сообщения и сразу же записать это в БД
292
         *
293
         * @param iMessage[]|object[] $messages
294
         *
295
         * @return string[]|integer[]
296
         * @throws QueueException
297
         */
298 2352
        function delete_messages(array $messages) {
299
            /**
300
             * @var string[][] $filenames_contains_keys
301
             * @var string[]   $filenames
302
             */
303 2352
            list($filenames, $filenames_contains_keys) = $this->get_filenames_from_messages($messages);
304 2352
            $filenames_contains_keys_all = [];
305 2352
            foreach ($this->_key_to_file as $key => $filename) {
306 2352
                if (isset($filenames_contains_keys_all[$filename])) {
307 1773
                    $filenames_contains_keys_all[$filename][] = $key;
308 591
                } else {
309 2352
                    $filenames_contains_keys_all[$filename] = [$key];
310
                }
311 784
            }
312 2352
            unset($key, $filename);
313
314 2352
            $deleted_keys = [];
315 2352
            foreach ($filenames as $filename) {
316 2352
                if (!file_exists($filename)) {
317
                    // @todo Надо подумать правильный ли это подход
318
                    // Тут будут все ключи, а не только те, которые надо было удалить
319 1812
                    $deleted_keys = array_merge($deleted_keys, $filenames_contains_keys[$filename]);
320 1812
                    continue;
321
                }
322 2352
                if (!is_writable($filename)) {
323
                    throw new QueueException('Can not delete messages from read only files');
324
                }
325 2352
                if (count($filenames_contains_keys[$filename]) == count($filenames_contains_keys_all[$filename])) {
326
                    // Нужно удалить все записи в файле, значит можно просто удалить файл целиком
327 1806
                    if (!unlink($filename)) {
328
                        // @codeCoverageIgnoreStart
329
                        throw new QueueException('Can not delete file '.$filename);
330
                        // @codeCoverageIgnoreEnd
331
                    }
332 1806
                    $deleted_keys = array_merge($deleted_keys, $filenames_contains_keys[$filename]);
333 1806
                    continue;
334
                }
335
336 606
                $fo = fopen($filename, 'r');
337 606
                $locked = flock($fo, LOCK_EX);
338 606
                if (!$locked) {
339
                    fclose($fo);
340
                    throw new QueueException('Can not delete file '.$filename);
341
                }
342 606
                $buf = file_get_contents($filename);
343 606
                if (empty($buf)) {
344
                    flock($fo, LOCK_UN);
345
                    fclose($fo);
346
                    throw new QueueException('File "'.$filename.'" is empty');
347
                }
348
                /**
349
                 * @var SmallFilesQueueSingleFile $data
350
                 */
351 606
                $data = @unserialize($buf);
352 606
                if (!is_object($data)) {
353
                    flock($fo, LOCK_UN);
354
                    fclose($fo);
355
                    throw new QueueException('File "'.$filename.'" does not contain Single Queue object');
356
                }
357 606
                if ($data->queue_name != $this->get_queue_name()) {
0 ignored issues
show
Bug introduced by
Accessing queue_name on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
358
                    flock($fo, LOCK_UN);
359
                    fclose($fo);
360
                    throw new QueueException('Invalid queue name ("'.$data->queue_name.
0 ignored issues
show
Bug introduced by
Accessing queue_name on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
361
                                             '" instead of "'.$this->get_queue_name().'")');
362
                }
363 606
                if ($data->version != self::SINGLE_FILE_DB_VERSION) {
0 ignored issues
show
Bug introduced by
Accessing version on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
364
                    flock($fo, LOCK_UN);
365
                    fclose($fo);
366
                    continue;
367
                }
368 606
                $data->time_last_update = microtime(true);
0 ignored issues
show
Bug introduced by
Accessing time_last_update on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
369
370 606
                $new_queue = [];
371 606
                foreach ($data->queue as $message) {
0 ignored issues
show
Bug introduced by
Accessing queue on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
372 606
                    $key = self::get_real_key_for_message($message);
373 606
                    if (!in_array($key, $filenames_contains_keys[$filename])) {
374 606
                        $message->is_read = true;
375 606
                        $new_queue[] = $message;
376 202
                    } else {
377 606
                        $deleted_keys[] = $key;
378
                    }
379 202
                }
380 606
                if (empty($new_queue)) {
381
                    // @hint На самом деле это невозможно
382 606
                    flock($fo, LOCK_UN);
383 606
                    fclose($fo);
384 606
                    if (!unlink($filename)) {
385
                        // @codeCoverageIgnoreStart
386
                        throw new QueueException('Can not delete file '.$filename);
387
                        // @codeCoverageIgnoreEnd
388
                    }
389 606
                    continue;
390
                }
391 606
                $data->queue = $new_queue;
0 ignored issues
show
Bug introduced by
Accessing queue on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
392 606
                $u = file_put_contents($filename, serialize($data));
393 606
                if ($u === false) {
394
                    // @codeCoverageIgnoreStart
395
                    throw new QueueException('Can not save single query file "'.$filename.'"');
396
                    // @codeCoverageIgnoreEnd
397
                }
398 606
                flock($fo, LOCK_UN);
399 606
                fclose($fo);
400 784
            }
401
402 2352
            return array_unique($deleted_keys);
403
        }
404
405
        /**
406
         * Обновляем сообщение и сразу же сохраняем всё
407
         *
408
         * Эта функция не рейзит ошибку, если сообщение не найдено
409
         *
410
         * @param iMessage|object $message
411
         * @param string|null     $key форсированно задаём ключ сообщения
412
         *
413
         * @return boolean
414
         * @throws QueueException
415
         */
416 240
        function update_message($message, $key = null) {
417 240
            $this_key = !is_null($key) ? $key : self::get_real_key_for_message($message);
418
419 240
            if (!isset($this->_key_to_file[$this_key])) {
420
                // Нет такого файла в списке
421 120
                return false;
422
            }
423 240
            $filename = $this->_key_to_file[$this_key];
424 240
            if (!file_exists($filename)) {
425
                return false;
426
            }
427 240
            if (!is_readable($filename)) {
428
                throw new QueueException('Can not update read only file');
429
            }
430
431 240
            $fo = fopen($filename, 'r');
432 240
            $locked = flock($fo, LOCK_EX);
433 240
            if (!$locked) {
434
                fclose($fo);
435
                throw new QueueException('Can not delete file '.$filename);
436
            }
437 240
            $buf = file_get_contents($filename);
438 240
            if (empty($buf)) {
439
                flock($fo, LOCK_UN);
440
                fclose($fo);
441
                throw new QueueException('File "'.$filename.'" is empty');
442
            }
443
            // @todo обрабатывать ошибки
444
            /**
445
             * @var SmallFilesQueueSingleFile $data_in
446
             */
447 240
            $data_in = @unserialize($buf);
448 240
            if (!is_object($data_in)) {
449
                flock($fo, LOCK_UN);
450
                fclose($fo);
451
                throw new QueueException('File "'.$filename.'" does not contain Single Queue object');
452
            }
453 240
            if ($data_in->version != self::SINGLE_FILE_DB_VERSION) {
0 ignored issues
show
Bug introduced by
Accessing version on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
454
                flock($fo, LOCK_UN);
455
                fclose($fo);
456
                throw new QueueException('Single DB File version mismatch ('.$data_in->version.
0 ignored issues
show
Bug introduced by
Accessing version on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
457
                                         ' instead of '.self::SINGLE_FILE_DB_VERSION.')');
458
            }
459 240
            if ($data_in->queue_name != $this->get_queue_name()) {
0 ignored issues
show
Bug introduced by
Accessing queue_name on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
460
                flock($fo, LOCK_UN);
461
                fclose($fo);
462
                throw new QueueException('Invalid queue name ("'.$data_in->queue_name.
0 ignored issues
show
Bug introduced by
Accessing queue_name on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
463
                                         '" instead of "'.$this->get_queue_name().'")');
464
            }
465 240
            $data_in->time_last_update = microtime(true);
0 ignored issues
show
Bug introduced by
Accessing time_last_update on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
466
467
            // Ищем то же сообщение и заменяем его
468 240
            $exists = $this->change_message_in_array($data_in->queue, $message, $this_key);
0 ignored issues
show
Bug introduced by
Accessing queue on the interface NokitaKaze\Queue\SmallFilesQueueSingleFile 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...
469 240
            if ($exists) {
470 240
                $u = file_put_contents($filename, serialize($data_in));
471 240
                if ($u === false) {
472
                    // @codeCoverageIgnoreStart
473
                    throw new QueueException('Can not save single query file "'.$filename.'"');
474
                    // @codeCoverageIgnoreEnd
475
                }
476 80
            }
477 240
            flock($fo, LOCK_UN);
478 240
            fclose($fo);
479
480 240
            return $exists;
481
        }
482
483
        /**
484
         * Поддерживает ли очередь сортировку event'ов при вставке
485
         *
486
         * @return boolean
487
         */
488 3
        static function is_support_sorted_events() {
489 3
            return false;
490
        }
491
492
        /*
493
         * @param double|integer $wait_time
494
         *
495
         * @return iMessage|object|null
496
         *
497
         * @throws QueueException
498
         * @codeCoverageIgnore
499
         /
500
        protected function consume_next_message_with_inotify($wait_time = -1) {
501
            $start = microtime(true);
502
            // @todo написать
503
            throw new QueueException('Не готово');
504
        }
505
        */
506
507
        /*
508
         * @codeCoverageIgnore
509
         /
510
        function test_inotify() {
511
            // @todo этого тут быть не должно
512
            $a = inotify_init();
513
        }
514
        */
515
516
        /**
517
         * @param SmallFilesQueueTransport $queue
518
         *
519
         * @return boolean
520
         */
521 1248
        function is_equal_to($queue) {
522 1248
            if (spl_object_hash($this) == spl_object_hash($queue)) {
523 3
                return true;
524
            }
525 1248
            if (!parent::is_equal_to($queue)) {
526 1242
                return false;
527
            }
528
529 6
            return (($queue->_message_folder == $this->_message_folder) and
530 6
                    ($queue->get_queue_name() == $this->get_queue_name()));
531
        }
532
    }
533
534
?>