tasks = $data['EventManager.scheduledTasks']; } /** * Gets object data for caching * * @return Array * @access public */ public function getToCache() { return Array ( 'EventManager.scheduledTasks' => $this->tasks, ); } /** * Returns information about registered scheduled tasks * * @param bool $from_cache * @return Array * @access public */ public function getAll($from_cache = false) { static $scheduled_tasks = null; if ( $from_cache ) { return $this->tasks; } if ( !isset($scheduled_tasks) ) { $timeout_clause = 'LastRunStatus = ' . ScheduledTask::LAST_RUN_RUNNING . ' AND Timeout > 0 AND ' . adodb_mktime() . ' - LastRunOn > Timeout'; $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('scheduled-task', 'TableName') . ' WHERE (Status = ' . STATUS_ACTIVE . ') AND ((LastRunStatus != ' . ScheduledTask::LAST_RUN_RUNNING . ') OR (' . $timeout_clause . '))'; $scheduled_tasks = $this->Conn->Query($sql, 'Name'); } return $scheduled_tasks; } /** * Add new scheduled task * * @param string $short_name name to be used to store last maintenance run info * @param string $event_string * @param int $run_schedule run schedule like for Cron * @param int $status * @access public */ public function add($short_name, $event_string, $run_schedule, $status = STATUS_ACTIVE) { $this->tasks[$short_name] = Array ( 'Event' => $event_string, 'RunSchedule' => $run_schedule, 'Status' => $status ); } /** * Run registered scheduled tasks with specified event type * * @param bool $from_cron * @access public */ public function runAll($from_cron = false) { if ( defined('IS_INSTALL') ) { return ; } $use_cron = $this->Application->ConfigValue('RunScheduledTasksFromCron'); if ( ($use_cron && !$from_cron) || (!$use_cron && $from_cron) ) { // match execution place with one, set in config return ; } ignore_user_abort(true); set_time_limit(0); $events_source = $this->getAll(); $user_id = $this->Application->RecallVar('user_id'); $this->Application->StoreVar('user_id', USER_ROOT, true); // to prevent permission checking inside events, true for optional storage /** @var SiteHelper $site_helper */ $site_helper = $this->Application->recallObject('SiteHelper'); $site_domain_id = $site_helper->getDomainByName('DomainName', DOMAIN); foreach ($events_source as $short_name => $event_data) { // Scheduled task was updated from another process. if ( $this->getLiveData($short_name) != $event_data ) { continue; } if ( $site_domain_id && $event_data['SiteDomainLimitation'] != '' ) { $site_domains = explode('|', substr($event_data['SiteDomainLimitation'], 1, -1)); if ( !in_array($site_domain_id, $site_domains) ) { // scheduled task isn't allowed on this site domain continue; } } // remember LastTimeoutOn only for events that are still running and will be reset if ( $event_data['LastRunStatus'] == ScheduledTask::LAST_RUN_RUNNING ) { $this->update($short_name, Array ('LastTimeoutOn' => adodb_mktime())); } $next_run = (int)$event_data['NextRunOn']; if ($next_run && ($next_run > adodb_mktime())) { continue; } $event_data['Name'] = $short_name; $this->run($event_data); } $this->Application->StoreVar('user_id', $user_id, $user_id == USER_GUEST); } /** * Returns LIVE scheduled task data. * * @param string $short_name Short scheduled task name. * * @return array */ protected function getLiveData($short_name) { $sql = 'SELECT * FROM ' . $this->Application->getUnitOption('scheduled-task', 'TableName') . ' WHERE Status = ' . STATUS_ACTIVE . ' AND Name = ' . $this->Conn->qstr($short_name); return $this->Conn->GetRow($sql); } /** * Runs scheduled task based on given data * * @param Array $scheduled_task_data * @return bool * @access public */ public function run($scheduled_task_data) { $event = new kEvent($scheduled_task_data['Event']); if ( !$this->Application->prefixRegistred($event->Prefix) ) { // don't process scheduled tasks, left from disabled modules return false; } /** @var kCronHelper $cron_helper */ $cron_helper = $this->Application->recallObject('kCronHelper'); $start_time = adodb_mktime(); // remember, when scheduled task execution started $fields_hash = Array ( 'LastRunOn' => $start_time, 'LastRunStatus' => ScheduledTask::LAST_RUN_RUNNING, 'NextRunOn' => $cron_helper->getMatch($scheduled_task_data['RunSchedule'], $start_time), ); $this->update($scheduled_task_data['Name'], $fields_hash); $event->redirect = false; $this->Application->HandleEvent($event); $now = adodb_mktime(); $next_run = $cron_helper->getMatch($scheduled_task_data['RunSchedule'], $start_time); while ($next_run < $now) { // in case event execution took longer, then RunSchedule (don't use <=, because RunSchedule can be 0) $next_run = $cron_helper->getMatch($scheduled_task_data['RunSchedule'], $next_run); } // remember, when scheduled task execution ended $fields_hash = Array ( 'NextRunOn' => $next_run, 'RunTime' => $now - $start_time, 'LastRunStatus' => $event->status == kEvent::erSUCCESS ? ScheduledTask::LAST_RUN_SUCCEEDED : ScheduledTask::LAST_RUN_FAILED, ); $this->update($scheduled_task_data['Name'], $fields_hash); return true; } /** * Updates scheduled task record with latest changes about it's invocation progress * * @param string $scheduled_task_name * @param Array $fields_hash * @return void * @access protected */ protected function update($scheduled_task_name, $fields_hash) { $this->Conn->doUpdate( $fields_hash, $this->Application->getUnitOption('scheduled-task', 'TableName'), 'Name = ' . $this->Conn->qstr($scheduled_task_name) ); } }