Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560 [2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85 [3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50 [4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13 [5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
| Server IP : 94.177.8.99 / Your IP : 216.73.217.165 Web Server : Apache/2.4.58 (Ubuntu) System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/theyoungdesigners_com/modules/crontab/model/ |
Upload File : |
<?php
class Cron_Model extends Database_Model {
const CRONTAB = '/usr/bin/crontab';
private $running = FALSE;
private function _Createkey($entrypoint, $includeSite = FALSE) {
$hash = $includeSite ? md5(__DIR__) . '/' : ''; // this essentially the site identifier
if (is_string($entrypoint)) {
return $hash . str_replace(['>', '<', ';', '|', '/'], '', strtolower($entrypoint));
}
if ($entrypoint[0] === NULL) {
$classname = 'null';
} else {
$class = get_class($entrypoint[0]);
if (is_a($entrypoint[0], 'moduleMain')) {
$elements = explode('\\', $class);
array_pop($elements);
$class = array_pop($elements);
}
$classname = strtolower($class);
}
$ep = str_replace(['_', '>', '<', ';', '|', '/'], ['-', '', '', '', '', ''], strtolower($entrypoint[1]));
return $hash . $classname . '/' . $ep;
}
// what version of php is being used, and where is the cli version?
// assumes linux
public function getExecutable() {
$major = PHP_MAJOR_VERSION;
$minor = PHP_MINOR_VERSION;
$dir = PHP_BINDIR;
$executable = "$dir/php{$major}.{$minor}";
if (file_exists($executable)) return $executable;
$executable = "$dir/php{$major}";
if (file_exists($executable)) return $executable;
$executable = '/etc/alternatives/php'; // default php
if (is_link($executable)) {
return readlink($executable);
}
return PHP_BINARY;
}
public function CreateCommandLine($entrypoint) {
$key = $this->_Createkey($entrypoint, FALSE);
$exe = $this->getExecutable();
if (is_string($entrypoint) && file_exists($entrypoint)) {
$command = $exe . ' -q ' . $entrypoint;
} elseif (is_a($entrypoint[0], 'controller')) {
$command = $exe . ' -q ' . HOME . '/public/index.php "uri=' . $key . '"';
} elseif (is_a($entrypoint[0], 'moduleMain')) {
$command = $exe . ' -q ' . HOME . '/public/index.php "uri=/~/' . $key . '"';
} elseif (is_string($entrypoint)) {
$command = $exe . ' -q ' . HOME . '/public/index.php "uri=' . $entrypoint . '"';
} else {
return '';
}
return $command;
}
private function _loadCron() {
$command = self::CRONTAB . ' -l';
$output = `export CRONTAB_NOHEADER=NO; $command`;
// $output = `$command`;
$lines = explode("\n", trim($output));
// remove crontab lines if present
$c = count($lines);
if ($c >= 3) {
if (strpos($lines[2], 'Cron version') !== FALSE) {
unset($lines[2]);
if (strpos($lines[1], 'installed on') !== FALSE) {
unset($lines[1]);
}
if (strpos($lines[0], 'DO NOT EDIT THIS FILE') !== FALSE) {
unset($lines[0]);
}
}
}
return $lines;
}
private function _saveCron($cron) {
$tmp = tempnam(sys_get_temp_dir(), 'cron');
$items = join("\n", $cron) . "\n";
file_put_contents($tmp, $items);
$command = self::CRONTAB . ' < ' . $tmp;
$x = `$command 2>&1`;
unlink($tmp);
return $x;
}
public function AddCron($time, $entrypoint, $debug = FALSE) {
$key = $this->_CreateKey($entrypoint, TRUE);
$command = $this->CreateCommandLine($entrypoint);
if ($debug) {
$tmp = sys_get_temp_dir();
$command .= ' >> ' . $tmp . '/' . str_replace('/', '-', $key) . '.log 2>&1';
} else {
$command .= ' > /dev/null 2>&1';
}
$key = '##' . $key;
$cron = $this->_loadCron();
$text = $time . ' ' . $command;
$found = 0;
foreach($cron as $index => $cron_item) {
if ($cron_item == $key) {
if ($cron[$index+1] == $text) return TRUE; // unchanged - no need to update
$found = 1;
$cron[$index+1] = $text;
}
}
if (!$found) {
// if we have the command elsewhere in the cron, remove it
$text = $time . ' ' . $command;
if (($p = strpos($command, '>')) !== FALSE) {
$basecommand = substr($command, 0, $p);
} else {
$basecommand = $command;
}
foreach($cron as $index => $cron_item) {
if (strpos($cron_item, $basecommand) !== FALSE) {
unset($cron[$index]);
}
}
$cron[] = $key;
$cron[] = $text;
}
return $this->_SaveCron($cron);
}
public function RemoveCron($entrypoint) {
$key = '##' . $this->_CreateKey($entrypoint, TRUE);
$cron = $this->_loadCron();
foreach($cron as $index => $cron_item) {
if ($cron_item == $key) {
unset($cron[$index+1]);
unset($cron[$index]);
$this->_SaveCron($cron);
return TRUE;
}
}
return FALSE;
}
// keep track of running events - and when each one is scheduled to run next
// is event set to run this time? Lock it so that at next tick, it will not run. unlock when execution is eventually complete
public function Tick($now = 0) {
if (!$now) $now = time();
// error_log(gmdate('Y-m-d H:i ', $now) . "Tick");
// echo gmdate('Y-m-d H:i ', $now) . "Tick\n";
// get a list of scheduled events
$events = hook_list('cron');
//when should each one execute next?
$next_event_time = [];
if ($events !== NULL) {
foreach($events as $priority => $hook_entries) {
foreach($hook_entries as $event) {
$id = $event->ID();
$next_event_time[$id] = [
'start_time' => 0,
'running' => false,
'event' => $event
];
}
}
}
// get next run time for all events
$records = array_keys($next_event_time);
$this->query('select * from `events`')
->whereOr($this->wherein('event_id', $records), $this->where('event_id like "%:%"') );
$data = $this->get();
$this->DbErr();
foreach($data as $dataitem) {
$id = $dataitem->event_id;
$next_event_time[$id]['start_time'] = $dataitem->start_time;
$next_event_time[$id]['running'] = !empty($dataitem->running);
$next_event_time[$id]['data'] = $dataitem->AsArray();
}
$this->tablename('events');
foreach($next_event_time as $id => &$param) {
$update = FALSE;
if (strpos($id, ':') !== FALSE) { // this is a delayed custom event
[ $event_type, $event_id ] = explode(':', $id, 2);
$param = hook_execute('custom.event.' . $event_type, $param); // create an event object
$update = $param['update'] ?? FALSE;
$param['running'] = FALSE;
} elseif ($param['start_time'] < $now - 30 && !$param['running'] && $param['start_time'] > 0) { // if not running, or last event expired
$param['start_time'] = $param['event']->NextEvent($now);
$update = TRUE;
} elseif ($param['running'] && $param['start_time'] < $now - 3600) { // if execution too long:
// 2019/04 THIS IS THE CURRENT PROBLEM - Process is currently "running"
// timeout/error check: if running, and event start time was more than an hour, reset status, determine next event time
$param['start_time'] = $param['event']->NextEvent($now);
$param['running'] = FALSE;
$update = TRUE;
} elseif (!$param['start_time'] && !$param['running']) { // never run before - create the first entry
$param['start_time'] = $param['event']->NextEvent($now);
$update = TRUE;
}
if ($update) {
// get name of entrypoint
$callback = $param['event']->Execute();
if (is_array($callback)) {
$callback = get_class($callback[0]) . '::' . $callback[1];
// error_log(gmdate('Y-m-d H:i ', $now) . "- $callback");
} else {
$callback = NULL;
}
if (empty($param['start_time'])) $param['start_time'] = 0; // this event does not have a specific cron-based start time
$this->InsertOrUpdate([
'event_id' => $param['event']->ID(),
],[
'start_time' => $param['start_time'],
'running' => $param['running'] ? 1 : 0,
'cmt_date' => gmdate('Y-m-d H:i', $param['start_time']),
'cmt_module' => $callback,
]);
// $this->DbErr();
}
}
unset($param);
foreach($next_event_time as $id => $param) {
/* $x = $now + 30;
$running = $param['running'] ? 'running' : 'not running';
$fs = gmdate('Y-m-d H:i:s', $param['start_time']);
$fx = gmdate('Y-m-d H:i:s', $x);
echo "$id: {$param['start_time']} < {$x} - $running\n";
echo "requested start time: {$fs} < current time: {$fx}\n"; */
if ($param['start_time'] > 0 && $param['start_time'] < $now + 30 && !$param['running'] && is_object($param['event'])) {
$fx = gmdate('Y-m-d H:i');
echo "$fx - Launching process $id...\n";
error_log("$fx - Launching process $id...");
$this->Execute($param['event'], $now); // spawn new process in background
}
}
}
public function IsRunning() {
return $this->running;
}
public function Execute($event, $now = 0, $updateDatabase = TRUE ) {
if (function_exists('pcntl_fork')) { // from command command line (via crontab)
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
// execute synch?
} else if ($pid) { // are we the parent - do nothing
} else { // we are the child
$this->_executeEvent($event, $now, $updateDatabase); // spawn new process
exit;
}
} else {
error_log(gmdate('Y-m-d H:i ', $now) . " - no pcntl_fork");
// run from apache/web request
$this->_executeEvent($event, $now, $updateDatabase);
}
}
private function _executeEvent($event, $now = 0, $updateDatabase = TRUE) {
try {
$this->Database_Reopen(); // To fix "Database error: Error: MySQL server has gone away [2006]";
if ($updateDatabase) {
if (!$now) $now = time();
$new_time = $event->NextEvent($now + 30);
if ($new_time === FALSE) $new_time = 0;
$this->TableName('events')
->InsertOrUpdate([
'event_id' => $event->ID(),
],[
'start_time' => $new_time,
'cmt_date' => gmdate('Y-m-d H:i', $new_time),
'running' => 1,
]);
}
// execute callback function
$this->running = TRUE;
$callback = $event->Execute();
if (is_callable($callback)) {
call_user_func($callback, $event);
}
$this->running = FALSE;
} catch (\Exception $e) {
echo "Exception: " . $e->getMessage() . "\n";
// log exception?
}
if ($updateDatabase) {
$this->TableName('events')
->InsertOrUpdate([
'event_id' => $event->ID(),
],[
'running' => 0,
]);
$this->DbErr();
}
}
}