PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / includes / class-wp-optimize-tasks-queue.php

class-wp-optimize-tasks-queue.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.7.0, at includes/class-wp-optimize-tasks-queue.php

351 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) die('No direct access allowed');
4
5 /**
6 * Class WP_Optimize_Tasks_Queue
7 */
8 class WP_Optimize_Tasks_Queue {
9
10 private $_queue_id;
11
12 private $_queue_key;
13
14 private $_queue;
15
16 private $_meta = array();
17
18 private static $_instances = array();
19
20 private $_lock;
21
22 private $_locked = null;
23
24 private $_logger;
25
26 /**
27 * WP_Optimize_Tasks_Queue constructor.
28 *
29 * @param string $queue_id
30 */
31 public function __construct($queue_id) {
32 $this->_queue_id = $queue_id;
33 $this->_queue_key = 'wpo_queue_' . $this->_queue_id;
34 $this->_lock = new Updraft_Semaphore_3_0($queue_id);
35 // loggers for semaphore
36 if (!empty(WP_Optimize()->wpo_loggers())) {
37 $this->_lock->set_loggers(WP_Optimize()->wpo_loggers());
38 }
39 $this->_logger = new Updraft_PHP_Logger();
40 }
41
42 /**
43 * Lock queue.
44 *
45 * @return bool
46 */
47 public function lock() {
48 $this->log('WP_Optimize_Tasks_Queue->lock()');
49 $this->_locked = $this->_lock->lock();
50 return $this->_locked;
51 }
52
53 /**
54 * Unlock queue.
55 */
56 public function unlock() {
57 $this->log('WP_Optimize_Tasks_Queue->unlock()');
58 $this->_lock->release();
59 $this->_locked = null;
60 }
61
62 /**
63 * Wait until queue will free.
64 */
65 public function wait() {
66 if ($this->is_locked()) return;
67
68 $this->log('WP_Optimize_Tasks_Queue->wait()');
69
70 $time_start = microtime(true);
71 $time_limit = 5; // limit time seconds.
72
73 while (false === $this->lock() && ($time_limit > (microtime(true) - $time_start))) {
74 $this->sleep(0.5);
75 }
76 }
77
78 /**
79 * Returns true if queue is locked.
80 *
81 * @return bool
82 */
83 public function is_locked() {
84 return (null === $this->_locked || true === $this->_locked);
85 }
86
87 /**
88 * Return instance of WP_Optimize_Tasks_Queue.
89 *
90 * @param string $queue_id
91 * @return WP_Optimize_Tasks_Queue
92 */
93 public static function this($queue_id = 'queue') {
94 if (!array_key_exists($queue_id, self::$_instances)) {
95 self::$_instances[$queue_id] = new WP_Optimize_Tasks_Queue($queue_id);
96
97 self::$_instances[$queue_id]->load();
98 }
99
100 return self::$_instances[$queue_id];
101 }
102
103 /**
104 * Delete queue form database.
105 */
106 public function delete_queue() {
107 global $wpdb;
108
109 $this->log('WP_Optimize_Tasks_Queue->delete_queue()');
110
111 // disable action if queue is not locked.
112 if (!$this->is_locked()) return;
113
114 $tasks_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT(tm.task_id) FROM `{$wpdb->base_prefix}tm_taskmeta` tm WHERE tm.meta_key='queue_id' AND tm.meta_value=%s", $this->_queue_id));
115
116 if (empty($tasks_ids)) return;
117
118 $tasks_ids = join(',', $tasks_ids);
119
120 $wpdb->query("DELETE t, tm FROM `{$wpdb->base_prefix}tm_tasks` t JOIN `{$wpdb->base_prefix}tm_taskmeta` tm ON t.id = tm.task_id WHERE t.id IN ($tasks_ids)"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Safe, tasks_ids are comma separated integers
121 }
122
123 public function clear_queue() {
124 $this->log('WP_Optimize_Tasks_Queue->clear_queue()');
125
126 $this->_queue = array();
127 }
128
129 /**
130 * Returns tru if queue is empty.
131 *
132 * @return bool
133 */
134 public function is_empty() {
135 return (0 == $this->length());
136 }
137
138 /**
139 * Returns count of tasks in queue.
140 *
141 * @return int
142 */
143 public function length() {
144 return count($this->_queue);
145 }
146
147 /**
148 * Add task to queue.
149 *
150 * @param WP_Optimize_Queue_Task $task
151 */
152 public function add_task($task) {
153 $this->log('WP_Optimize_Tasks_Queue->add_task({task})', array('task' => $task->get_info()));
154
155 // check if queue locked unsuccessfully, you don't need lock queue.
156 if (!$this->is_locked()) return;
157
158 $task->set_queue_id($this->_queue_id);
159 // $task->save();
160 $this->_queue[] = $task;
161 }
162
163 /**
164 * Load queue tasks form database.
165 */
166 public function load() {
167 global $wpdb;
168
169 $this->log('WP_Optimize_Tasks_Queue->load()');
170
171 // load tasks info from database.
172 $tasks = $wpdb->get_results("SELECT task_id, meta_key, meta_value FROM `{$wpdb->base_prefix}tm_taskmeta` t ORDER BY task_id", ARRAY_A);
173
174 $_tasks = array();
175
176 // arrange tasks info.
177 foreach ($tasks as $info) {
178 $task_id = $info['task_id'];
179 if (!array_key_exists($task_id, $_tasks)) $_tasks[$task_id] = array();
180
181 if ('task' === $info['meta_key']) {
182 $_info = WP_Optimize_Utils::maybe_unserialize($info['meta_value']);
183
184 if (is_array($_info)) {
185 foreach ($_info as $key => $value) {
186 $_tasks[$task_id][$key] = $value;
187 }
188 }
189 } else {
190 $_tasks[$task_id][$info['meta_key']] = WP_Optimize_Utils::maybe_unserialize($info['meta_value']);
191 }
192 }
193
194 $this->_queue = array();
195
196 // build queue.
197 foreach ($_tasks as $task_id => $info) {
198
199 // if unsupported task information then don't create task.
200 if (empty($info['task'])) continue;
201
202 $task = new WP_Optimize_Queue_Task($info['task'], $info['params'], $info['callback'], $info['priority']);
203 $task->set_id($task_id);
204 $task->set_queue_id($this->_queue_id);
205 $this->_queue[] = $task;
206 }
207
208 // sort queue tasks by priority
209 usort($this->_queue, array($this, 'cmp_order'));
210 }
211
212 /**
213 * Compare function for ordering tasks in queue by priority.
214 *
215 * @param WP_Optimize_Queue_Task $task_a
216 * @param WP_Optimize_Queue_Task $task_b
217 * @return int
218 */
219 public function cmp_order($task_a, $task_b) {
220 if ($task_a->priority == $task_b->priority) {
221 return ($task_a->get_id() < $task_b->get_id()) ? -1 : 1;
222 }
223
224 return ($task_a->priority < $task_b->priority) ? -1 : 1;
225 }
226
227 /**
228 * Save tasks to database and clear queue.
229 */
230 public function flush() {
231 if (!$this->is_locked()) return;
232
233 $this->log('WP_Optimize_Tasks_Queue->flush()');
234
235 // save tasks those not exists in DB.
236 foreach ($this->_queue as $task) {
237 if (!$task->get_id()) $task->save();
238 }
239
240 // clear queue variable.
241 $this->clear_queue();
242 }
243
244 /**
245 * Returns next task from the queue.
246 *
247 * @return bool|WP_Optimize_Queue_Task
248 */
249 public function get_next_task() {
250 // global $wpdb;
251
252 $this->log('WP_Optimize_Tasks_Queue->get_next_task()');
253
254 // Find task in queue.
255
256 if (empty($this->_queue)) return false;
257
258 $next_task_i = false;
259
260 foreach ($this->_queue as $i => $task) {
261 if (false === $next_task_i || $this->_queue[$next_task_i]->priority > $task->priority) {
262 $next_task_i = $i;
263 }
264 }
265
266 // $task = $wpdb->get_results($wpdb->prepare("SELECT t.task_id FROM `{$wpdb->base_prefix}tm_tasks` t JOIN `{$wpdb->base_prefix}tm_taskmeta` tm ON t.task_id = tm.task_id WHERE t.status='active' AND tm.meta_key='priority' AND t.task_id IN (SELECT DISTINCT(tm.task_id) FROM {$wpdb->base_prefix}tm_taskmeta tm WHERE tm.meta_key='queue_id' AND tm.meta_value=%s) ORDER BY tm.meta_value, t.task_id LIMIT 1", $this->_queue_id));
267
268 if (false !== $next_task_i) {
269 $next_task = $this->_queue[$next_task_i];
270 unset($this->_queue[$next_task_i]);
271
272 return $next_task;
273 }
274
275 return false;
276 }
277
278 /**
279 * Do next task from queue.
280 */
281 public function do_next_task() {
282 $this->log('WP_Optimize_Tasks_Queue->do_next_task()');
283
284 // disable action if queue is not locked.
285 if (!$this->is_locked()) {
286 // short sleep before next try.
287 $this->sleep(0.5);
288 $this->lock();
289 return;
290 }
291
292 $task = $this->get_next_task();
293
294 // do task.
295 if (is_object($task) && is_a($task, 'WP_Optimize_Queue_Task')) {
296
297 $this->log('WP_Optimize_Tasks_Queue->run({task})', array('task' => $task->get_info()));
298 $task->run();
299
300 $task->delete_meta();
301 $task->delete();
302 }
303 }
304
305 /**
306 * Save meta value for queue.
307 *
308 * @param string $name
309 * @param mixed $value
310 */
311 public function set_meta($name, $value) {
312 $this->_meta[$name] = $value;
313 }
314
315 /**
316 * Return meta value.
317 *
318 * @param string $name
319 * @return mixed|null
320 */
321 public function get_meta($name) {
322 if (array_key_exists($name, $this->_meta)) return $this->_meta[$name];
323
324 return null;
325 }
326
327 /**
328 * Sleep for $seconds.
329 *
330 * @param float $seconds
331 */
332 private function sleep($seconds) {
333 $second = 1000000; // microseconds in second.
334 usleep(floor($seconds * $second));
335 }
336
337 /**
338 * Log message into PHP log.
339 *
340 * @param string $message
341 * @param array $context
342 */
343 private function log($message, $context = array()) {
344
345 if (defined('WP_OPTIMIZE_UNUSED_IMAGES_LOG') && WP_OPTIMIZE_UNUSED_IMAGES_LOG) {
346 $this->_logger->debug($message, $context);
347 }
348
349 }
350 }
351