PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / libraries / system / cron.php

cron.php in VikBooking Hotel Booking Engine & PMS trunk, at libraries/system/cron.php

543 lines 13.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking - Libraries
4 * @subpackage system
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2018 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Class used to handle the cron jobs execution.
16 *
17 * @since 1.5.10
18 */
19 class VikBookingCron
20 {
21 /**
22 * Schedules the published cron jobs to be executed according
23 * to the selected recurrence.
24 *
25 * @return void
26 */
27 public static function setup()
28 {
29 static $setup = false;
30
31 if ($setup)
32 {
33 // setup is allowed only once
34 return;
35 }
36
37 // prevent double setup
38 $setup = true;
39
40 /**
41 * Filters the non-default cron schedules.
42 * Adds support to repeat the cron jobs every 5 minutes, every half hour,
43 * every 2 hours, and every month.
44 *
45 * @param array $schedules An array of non-default cron schedules.
46 */
47 add_filter('cron_schedules', function($schedules)
48 {
49 // add support for "every 5 minutes" recurrence
50 $schedules['every_5_minutes'] = array(
51 'interval' => MINUTE_IN_SECONDS * 5,
52 'display' => __('Every 5 Minutes', 'vikbooking'),
53 );
54
55 // add support for "every 15 minutes" recurrence
56 $schedules['every_15_minutes'] = array(
57 'interval' => MINUTE_IN_SECONDS * 15,
58 'display' => __('Every 15 Minutes', 'vikbooking'),
59 );
60
61 // add support for "every 30 minutes" recurrence
62 $schedules['half_hour'] = array(
63 'interval' => HOUR_IN_SECONDS / 2,
64 'display' => __('Every Half Hour', 'vikbooking'),
65 );
66
67 // add support for "every 2 hours" recurrence
68 $schedules['every_2_hours'] = array(
69 'interval' => HOUR_IN_SECONDS * 2,
70 'display' => __('Every 2 Hours', 'vikbooking'),
71 );
72
73 // add support for "every month" recurrence
74 $schedules['monthly'] = array(
75 'interval' => MONTH_IN_SECONDS,
76 'display' => __('Monthly', 'vikbooking'),
77 );
78
79 return $schedules;
80 });
81
82 /**
83 * Trigger event to allow the plugins to include custom HTML within the view.
84 * It is possible to return an associative array to group the HTML strings
85 * under different fieldsets. Plain/html string will be always pushed within
86 * the "custom" fieldset instead.
87 *
88 * Displays the field to select the cron job recurrence.
89 *
90 * @param mixed $forms The HTML to display.
91 * @param mixed $view The current view instance.
92 *
93 * @since 1.5.10
94 */
95 add_filter('vikbooking_display_view_cron', array('VikBookingCron', 'addScheduleControlForm'), 10, 2);
96
97 /**
98 * Trigger event to allow the plugins to make something before saving
99 * a record in the database. Used to extend the cron jobs management
100 * in order to support the selection of the recurrence.
101 *
102 * @param bool $save False to abort the saving process.
103 * @param array $args The saved record.
104 *
105 * @since 1.5.10
106 */
107 add_filter('vikbooking_before_save_cronjob', array('VikBookingCron', 'saveScheduleControl'), 10, 2);
108
109 /**
110 * Trigger event to allow the plugins to make something after saving
111 * a record in the database. Used to schedule the cron job execution.
112 *
113 * @param mixed $status The saving status.
114 * @param array $args The saved record.
115 * @param bool $is_new True in case of insert.
116 *
117 * @since 1.5.10
118 */
119 add_filter('vikbooking_after_save_cronjob', array('VikBookingCron', 'checkSchedulingAfterSave'), 10, 3);
120
121 /**
122 * Trigger event to allow the plugins to make something after publishing or
123 * unpublishing one or more records. Used to unschedule the unpublished cron jobs.
124 *
125 * @param bool $delete False to abort the deleting process.
126 * @param array $ids An array of IDs to delete.
127 *
128 * @since 1.5.10
129 */
130 add_filter('vikbooking_before_delete_cronjob', array('VikBookingCron', 'checkSchedulingBeforeDelete'), 10, 2);
131
132 // fetch list of cron jobs
133 $crons = static::getJobs();
134
135 if (!$crons)
136 {
137 // nothing to execute
138 return;
139 }
140
141 $model = VBOMvcModel::getInstance('cronjob');
142
143 // iterate cron jobs list
144 foreach ($crons as $id_cron)
145 {
146 // get cron job details
147 $cron = $model->getItem($id_cron);
148
149 if (!$cron)
150 {
151 // cron not found, go ahead
152 continue;
153 }
154
155 // fetch recurrence interval
156 $interval = !empty($cron->schedule_key) ? $cron->schedule_key : 'daily';
157
158 // build cron listener hook
159 $hook = static::getScheduleHook($cron);
160
161 /**
162 * Action used to execute all the cron jobs that have been created
163 * through the VikBooking panel. Only published cron jobs can
164 * be executed.
165 *
166 * The scheduling of this hook must be registered through
167 * WordPress in order to be executed.
168 */
169 add_action($hook, function() use ($id_cron)
170 {
171 VikBookingCron::runJob($id_cron);
172 });
173
174 // Make sure the cron event hasn't been yet scheduled.
175 // After its execution, wp_next_scheduled will return false and
176 // we will be able to register it again.
177 if (!wp_next_scheduled($hook))
178 {
179 // schedule event starting from the current time for every minute, by
180 // launching the cron listener hook (3rd argument)
181 wp_schedule_event(time(), $interval, $hook);
182 }
183 }
184 }
185
186 /**
187 * Executes the specified cron job.
188 *
189 * @param integer $id_cron The cron job ID.
190 *
191 * @return boolean True on success, false otherwise.
192 */
193 public static function runJob($id_cron)
194 {
195 // require the main library in case WPCron runs the job
196 require_once VBO_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikbooking.php';
197
198 $app = JFactory::getApplication();
199
200 /**
201 * Initialize timezone handler when WP-Cron executes the job to make sure we
202 * set the proper timezone. This is just for the scheduled cron job execution.
203 *
204 * @since 1.6.3
205 */
206 JDate::getDefaultTimezone();
207 date_default_timezone_set($app->get('offset', 'UTC'));
208
209 $error = null;
210 $status = false;
211
212 // force the option in request to prevent weird behaviors
213 $app->input->set('option', 'com_vikbooking');
214
215 // get CRON JOB model
216 $model = VBOMvcModel::getInstance('cronjob');
217
218 try
219 {
220 // dispatch cron job
221 $status = $model->dispatch($id_cron);
222
223 if (!$status)
224 {
225 // get any registered error
226 $error = $model->getError($last = null, $string = true);
227 }
228 }
229 catch (Exception $e)
230 {
231 // catch any exception and go ahead
232 $error = $e->getMessage();
233 }
234 catch (Throwable $e)
235 {
236 // catch any failure and go ahead
237 $error = sprintf('%s in %s on line %d', $e->getMessage(), $e->getFile(), $e->getLine());
238 }
239
240 if (!$status && $error)
241 {
242 $item = $model->getItem($id_cron);
243
244 if ($item)
245 {
246 // register error message within the logs of the cron job
247 $item->logs = "<div style=\"color:var(--vbo-red-color);\">$error</div>\n<hr />\n" . $item->logs;
248
249 $model->save($item);
250 }
251 }
252
253 /**
254 * Restore standard timezone when WP-Cron executes the job to make sure we
255 * set the proper timezone. This is just for the scheduled cron job execution.
256 *
257 * @since 1.6.3
258 */
259 date_default_timezone_set(JDate::getDefaultTimezone());
260
261 return $status;
262 }
263
264 /**
265 * Returns a list of published cron jobs.
266 *
267 * @param boolean True to return all the cron job columns.
268 *
269 * @return array An array of cron jobs.
270 */
271 public static function getJobs($all = false)
272 {
273 $dbo = JFactory::getDbo();
274
275 // retrieve all the published cron jobs
276 $q = $dbo->getQuery(true)
277 ->from($dbo->qn('#__vikbooking_cronjobs'))
278 ->where($dbo->qn('published') . ' = 1');
279
280 if ($all)
281 {
282 $q->select('*');
283 }
284 else
285 {
286 $q->select($dbo->qn('id'));
287 }
288
289 $dbo->setQuery($q);
290
291 if ($all)
292 {
293 return $dbo->loadObjectList();
294 }
295
296 return $dbo->loadColumn();
297 }
298
299 /**
300 * Creates the HTML to support a field for the selection of the
301 * recurrence while creating/editing a cron job.
302 *
303 * @param array $forms An associative array containing the HTML.
304 * @param object $view The view instance.
305 *
306 * @return array $forms The resulting HTML array.
307 */
308 public static function addScheduleControlForm($forms, $view)
309 {
310 if (!is_array($forms))
311 {
312 $forms = [];
313 }
314
315 if (!isset($forms['cronjob']))
316 {
317 // init details section
318 $forms['cronjob'] = '';
319 }
320
321 $schedule_key = null;
322
323 // check whether the schedule key property exists
324 if (!$view->row || !array_key_exists('schedule_key', $view->row))
325 {
326 static::installScheduleControl();
327 }
328 else
329 {
330 $schedule_key = $view->row['schedule_key'];
331 }
332
333 // fetch list of supported schedule intervals
334 $schedules = wp_get_schedules();
335
336 // sort the options in ascending order
337 uasort($schedules, function($a, $b)
338 {
339 return $a['interval'] - $b['interval'];
340 });
341
342 $options = [];
343
344 foreach ($schedules as $k => $schedule)
345 {
346 $options[] = JHtml::fetch('select.option', $k, $schedule['display']);
347 }
348
349 $options = JHtml::fetch('select.options', $options, 'value', 'text', $schedule_key ?: 'daily');
350
351 $label = __('Recurrence', 'vikbooking');
352
353 // build HTML control
354 $forms['cronjob'] .=
355 <<<HTML
356 <div class="vbo-param-container">
357 <div class="vbo-param-label">$label</div>
358 <div class="vbo-param-setting"><select name="schedule_key">$options</select></div>
359 </div>
360 HTML
361 ;
362
363 return $forms;
364 }
365
366 /**
367 * Executes while saving a cron job, so that it is possible to
368 * inject within the array to save the selected recurrence.
369 *
370 * @param boolean $save The saving flag.
371 * @param array &$src The array holding the data to save.
372 *
373 * @return boolean False to abort the saving process.
374 *
375 */
376 public static function saveScheduleControl($save, &$src)
377 {
378 if (is_null($save))
379 {
380 $save = true;
381 }
382
383 $src = (array) $src;
384
385 $input = JFactory::getApplication()->input;
386
387 // fetch schedule key from request
388 $schedule_key = $input->get('schedule_key', null, 'string');
389
390 // make sure the schedule key has been specified
391 if (!is_null($schedule_key))
392 {
393 // inject schedule key into the array to save
394 $src['schedule_key'] = $schedule_key;
395 }
396
397 return $save;
398 }
399
400 /**
401 * Checks the cron job scheduling after updating a record.
402 *
403 * @param boolean $status Dummy argument for WordPress bc.
404 * @param array $cron The cron jobs details.
405 * @param boolean $is_new True in case of insert.
406 *
407 * @return void
408 */
409 public static function checkSchedulingAfterSave($status, $cron, $is_new)
410 {
411 if (!$is_new)
412 {
413 // check only in case of update
414 static::checkJobScheduling($cron);
415 }
416 }
417
418 /**
419 * Unschedules the cron jobs that are going to be deleted.
420 *
421 * @param boolean $delete The deleting flag.
422 * @param object $item The item to delete.
423 *
424 * @return boolean False to abort the deleting process.
425 */
426 public static function checkSchedulingBeforeDelete($delete, $item)
427 {
428 if (is_null($delete))
429 {
430 $delete = true;
431 }
432
433 if ($delete)
434 {
435 // turn off publishing to detach the scheduling
436 $item->published = 0;
437
438 // trigger changes
439 static::checkJobScheduling($item);
440 }
441
442 return $delete;
443 }
444
445 /**
446 * Checks whether an existing schedule should be recreated as a result
447 * of any significant changes.
448 *
449 * @param array $cron The cron record.
450 *
451 * @return void
452 */
453 protected static function checkJobScheduling($cron)
454 {
455 $cron = (array) $cron;
456
457 if (!array_key_exists('published', $cron) || !array_key_exists('schedule_key', $cron))
458 {
459 // reload all the details of the updated cron job
460 $cron = VBOMvcModel::getInstance('cronjob')->getItem(@$cron['id']);
461 }
462 else
463 {
464 // cast to object
465 $cron = (object) $cron;
466 }
467
468 if (!$cron)
469 {
470 // ops...
471 return;
472 }
473
474 if (!isset($cron->schedule_key))
475 {
476 // property not yet installed, use the default one to properly
477 // unschedule the registered event
478 $cron->schedule_key = 'daily';
479 }
480
481 // build cron listener hook
482 $hook = static::getScheduleHook($cron);
483
484 // fetch the next scheduled event
485 $event = wp_get_scheduled_event($hook);
486
487 if (!$event)
488 {
489 // no scheduled event, do nothing...
490 return;
491 }
492
493 if (!$cron->published || $cron->schedule_key !== $event->schedule)
494 {
495 // unschedule the event
496 wp_unschedule_event($event->timestamp, $hook);
497 }
498 }
499
500 /**
501 * Returns the hook to be used while scheduling the execution
502 * of a cron job.
503 *
504 * @param object $cron The cron object.
505 *
506 * @return string The resulting hook.
507 */
508 protected static function getScheduleHook($cron)
509 {
510 $cron = (object) $cron;
511
512 // build cron listener hook
513 return implode('_', [
514 'vikbooking',
515 'cron',
516 preg_replace("/\.php$/", '', $cron->class_file),
517 $cron->id,
518 ]);
519 }
520
521 /**
522 * Install the resources needed to support a custom recurrence for
523 * the created cron jobs.
524 *
525 * @return void
526 */
527 protected static function installScheduleControl()
528 {
529 $fields = VBOMvcModel::getInstance('cronjob')->getTableColumns();
530
531 if (!isset($fields['schedule_key']))
532 {
533 $db = JFactory::getDbo();
534
535 // alter the table to allow the storage of the selected recurrence
536 $query = "ALTER TABLE `#__vikbooking_cronjobs` ADD COLUMN `schedule_key` varchar(64) DEFAULT NULL AFTER `published`";
537
538 $db->setQuery($query);
539 $db->execute();
540 }
541 }
542 }
543