PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.5
VikBooking Hotel Booking Engine & PMS v1.6.5
1.8.16 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 All 37 releases
vikbooking / libraries / system / cron.php

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

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