Completed
Push — developer ( 025f05...22f222 )
by Никита
41:41
created

Queue::unserialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
crap 2
1
<?php
2
3
    namespace NokitaKaze\Queue;
4
5
    class Queue extends AbstractQueueTransport {
6
        const ProducerThreadCount = 5;
7
        const DefaultDBFileCount = 10;
8
        const DefaultMessageFolderSubfolderCount = 10;
9
10
        const StorageTemporary = 0;
11
        const StoragePersistent = 1;
12
13
        /**
14
         * @var QueueTransport
15
         */
16
        protected $_general_queue = null;
17
18
        /**
19
         * @var QueueTransport[]
20
         */
21
        protected $_additional_queue = [];
22
23
        /**
24
         * @var GeneralQueueConstructionSettings|object $_settings
25
         */
26
        protected $_settings = null;
27
28
        /**
29
         * SmartQueue constructor.
30
         *
31
         * @param GeneralQueueConstructionSettings|object $settings
32
         *
33
         * @throws QueueException
34
         */
35 36
        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...
36 36
            $this->_settings = $settings;
37 36
            foreach ($settings->queues as $queue_settings) {
38
                /**
39
                 * @var string|QueueTransport $queue_class_name
40
                 * @var QueueTransport        $queue
41
                 */
42 36
                if (substr($queue_settings->class_name, 0, 1) == '\\') {
43
                    $queue_class_name = $queue_settings->class_name.'QueueTransport';
44
                } else {
45 36
                    $queue_class_name = __NAMESPACE__.'\\'.$queue_settings->class_name.'QueueTransport';
46
                }
47 36
                $queue = new $queue_class_name($queue_settings);
48
49 36
                if (isset($queue_settings->is_general) and $queue_settings->is_general) {
50 36
                    if (isset($this->_general_queue)) {
51
                        throw new QueueException('Two or more general queues');
52
                    }
53 36
                    $this->_general_queue = $queue;
54 36
                    $this->_additional_queue[] = clone $queue;
55 9
                } else {
56 33
                    $this->_additional_queue[] = $queue;
57
                }
58 9
            }
59 36
            if (is_null($this->_general_queue)) {
60
                throw new QueueException('Can not get general queue');
61
            }
62
            // @todo дописать
63 36
        }
64
65
        /**
66
         * @return string
67
         */
68 847
        static function generate_rnd_postfix() {
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...
69
            // mt_rand. **ДЁШЕВО** и сердито
70 847
            return mt_rand(1000000, 9999999).mt_rand(1000000, 9999999);
71
72
            // return RandomString::generate(6, RandomString::INCLUDE_NUMERIC | RandomString::INCLUDE_LOWER_LETTERS);
73
        }
74
75
        /**
76
         * Формируем сообщение для очереди
77
         *
78
         * @param mixed       $data
79
         * @param string|null $name Название сообщения. Если null, то можно дублировать
80
         * @param integer     $sort
81
         *
82
         * @return iMessage|object
83
         */
84 848
        static function build_message($data, $name = null, $sort = 5) {
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...
85
            return (object) [
86 848
                'name' => is_null($name) ? null : (string) $name,
87 848
                'data' => $data,
88 848
                'time_created' => microtime(true),
89 848
                'time_rnd_postfix' => is_null($name) ? static::generate_rnd_postfix() : null,
90 848
                'time_last_update' => microtime(true),
91 848
                'sort' => min(max($sort, 0), self::DefaultDBFileCount - 1),
92 212
                'is_read' => false,
93 212
            ];
94
        }
95
96
        /**
97
         * @param iMessage|object $object
98
         *
99
         * @return iMessage|object
100
         * @throws QueueException
101
         */
102 864
        static function sanify_event_object($object) {
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...
103 864
            $ret = clone $object;
104
            /** @noinspection PhpParamsInspection */
105 864
            if (!array_key_exists('name', $ret)) {
106 4
                $ret->name = null;
107 1
            }
108
            /** @noinspection PhpParamsInspection */
109 864
            if (!array_key_exists('data', $ret)) {
110 4
                throw new QueueException('Datum does not have field data', 12);
111
            }
112 864
            if (!isset($ret->sort)) {
113 4
                $ret->sort = 5;
114 1
            } else {
115 860
                $ret->sort = min(max($ret->sort, 0), Queue::DefaultDBFileCount - 1);
116
            }
117
118 864
            return $ret;
119
        }
120
121
        /**
122
         * Cloning sub queues
123
         */
124 376
        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...
125 376
            parent::__clone();
126 376
            $this->_general_queue = clone $this->_general_queue;
127 376
            foreach ($this->_additional_queue as &$sub_queue) {
128 376
                $sub_queue = clone $sub_queue;
129 94
            }
130 376
        }
131
132
        /**
133
         * implements Transport
134
         */
135
136
        /**
137
         * @param iMessage|object $message
138
         *
139
         * @return string
140
         */
141 1088
        static function get_real_key_for_message($message) {
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...
142 1088
            return !is_null($message->name)
143 953
                ? $message->name
144 1054
                : sprintf('_%s%s',
145 1043
                    number_format($message->time_created, 7, '.', ''),
146 1077
                    isset($message->time_rnd_postfix) ? '_'.$message->time_rnd_postfix : ''
147 272
                );
148
        }
149
150 8
        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...
151 8
            return $this->_settings->name;
152
        }
153
154 4
        static function is_support_sorted_events() {
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...
155 4
            return false;
156
        }
157
158 20
        function produce_message($data, $name = null, $sort = 5) {
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...
159 20
            $this->set_same_time_flag(1);
160 20
            $this->_general_queue->produce_message($data, $name, $sort);
161 20
        }
162
163 300
        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...
164 300
            $this->set_same_time_flag(1);
165 300
            $this->_general_queue->push($this->_pushed_for_save);
166 300
            $this->_pushed_for_save = [];
167 300
            $this->_general_queue->save();
168 300
        }
169
170
        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...
171
            $this->_general_queue->set_exclusive_mode($mode);
172
            foreach ($this->_additional_queue as $queue) {
173
                $queue->set_exclusive_mode($mode);
174
            }
175
        }
176
177
        /**
178
         * @var iMessage[]|object[]
179
         */
180
        protected $_next_messages = [];
181
182 352
        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...
183 352
            $this->set_same_time_flag(2);
184 352
            if (!empty($this->_next_messages)) {
185 316
                return array_shift($this->_next_messages);
186
            }
187 352
            $ts_start = microtime(true);
188 352
            $till_time = $ts_start + $wait_time;
189
190 352
            $first_run = false;
191
            do {
192 352
                if ($first_run) {
193 63
                    usleep($this->_settings->sleep_time_while_consuming * 1000000);
194 16
                } else {
195 352
                    $first_run = true;
196
                }
197 352
                $messages = [];
198 352
                foreach ($this->_additional_queue as $queue) {
199 352
                    while ($message = $queue->consume_next_message(0)) {
200 352
                        $key = self::get_real_key_for_message($message);
201 352
                        if (isset($this->_consumed_keys[$key])) {
202 136
                            continue;
203
                        }
204 352
                        $message->is_read = true;
205 352
                        $messages[] = $message;
206 352
                        $this->_consumed_keys[$key] = 1;
207 88
                    }
208
209 352
                    if (!empty($messages)) {
210 352
                        $this->_next_messages = $messages;
211 352
                        if (!$queue->is_equal_to($this->_general_queue)) {
212 152
                            $this->_general_queue->push($messages);
213 152
                            $this->_general_queue->save();
214 152
                            $queue->delete_messages($messages);
215 38
                        }
216
217 352
                        return array_shift($this->_next_messages);
218
                    }
219 87
                }
220 332
                unset($message, $key, $queue);
221 332
            } while (($wait_time == -1) or (microtime(true) <= $till_time));
222
223 332
            return null;
224
        }
225
226
        /**
227
         * Обновляем сообщение и сразу же сохраняем всё
228
         *
229
         * Эта функция не рейзит ошибку, если сообщение не найдено
230
         *
231
         * @param iMessage|object $message
232
         * @param string|null     $key форсированно задаём ключ сообщения
233
         *
234
         * @return boolean
235
         */
236 160
        function update_message($message, $key = null) {
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...
237 160
            $this_key = !is_null($key) ? $key : self::get_real_key_for_message($message);
238 160
            foreach ($this->_next_messages as $exists_message) {
239
                if (self::get_real_key_for_message($exists_message) == $this_key) {
240
                    $exists_message->data = $message->data;
241
                    $exists_message->time_last_update = microtime(true);
242
                    break;
243
                }
244 40
            }
245
246 160
            return $this->_general_queue->update_message($message, $key);
247
        }
248
249 4
        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...
250 4
            $this->_consumed_keys = [];
251 4
            foreach ($this->_additional_queue as $queue) {
252 4
                $queue->clear_consumed_keys();
253 1
            }
254 4
        }
255
256
        /**
257
         * Удалить сообщения и сразу же записать это в БД
258
         *
259
         * @param iMessage[]|object[] $messages
260
         *
261
         * @return string[]|integer[]
262
         */
263 136
        function delete_messages(array $messages) {
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...
264 136
            $deleted_keys = [];
265 136
            foreach ($this->_additional_queue as $queue) {
266 136
                $deleted_keys = array_merge($deleted_keys, $queue->delete_messages($messages));
267 34
            }
268
269 136
            return array_unique($deleted_keys);
270
        }
271
272
        /**
273
         * @param Queue $queue
274
         *
275
         * @return boolean
276
         */
277 4
        function is_equal_to($queue) {
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...
278 4
            if (spl_object_hash($this) == spl_object_hash($queue)) {
279 4
                return true;
280
            }
281 4
            if (!parent::is_equal_to($queue)) {
282
                return false;
283
            }
284 4
            if (!$this->_general_queue->is_equal_to($queue->_general_queue)) {
285
                return false;
286
            }
287 4
            foreach ($this->_additional_queue as $i => $sub_queue) {
288 4
                if (!$sub_queue->is_equal_to($queue->_additional_queue[$i])) {
289 3
                    return false;
290
                }
291 1
            }
292
293 4
            return true;
294
        }
295
296
        /**
297
         * @param mixed $data
298
         *
299
         * @return string
300
         */
301
        static function serialize($data) {
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...
302
            return \serialize($data);
303
        }
304
305
        /**
306
         * @param string  $string
307
         * @param boolean $is_valid
308
         *
309
         * @return mixed
310
         */
311
        static function unserialize($string, &$is_valid) {
2 ignored issues
show
Unused Code introduced by
The parameter $is_valid is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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...
312
            return @\unserialize($string);
313
        }
314
    }
315
316
?>