38        $this->logger->info(
"CRON - batch start");
 
   41        $this->
settings->set(
"last_cronjob_start_ts", $ts);
 
   46        $this->logger->info(sprintf(
 
   47            'Verification of last run datetime (read from database): %s',
 
   55        if (!defined(
"ILIAS_HTTP_PATH")) {
 
   60        foreach (self::getCronJobData(
null, 
false) as $row) {
 
   69        foreach (self::getPluginJobs(
true) as $item) {
 
   74        $this->logger->info(
"CRON - batch end");
 
   87        $ilLog = 
$DIC->logger()->root();
 
   91        $ilLog->write(
"CRON - manual start (" . $a_job_id . 
")");
 
   95            if ($job->isManuallyExecutable()) {
 
   98                $ilLog->write(
"CRON - job " . $a_job_id . 
" is not intended to be executed manually");
 
  101            $ilLog->write(
"CRON - job " . $a_job_id . 
" seems invalid or is inactive");
 
  104        $ilLog->write(
"CRON - manual end (" . $a_job_id . 
")");
 
  117    protected static function runJob(
ilCronJob $a_job, array $a_job_data = 
null, $a_manual = 
false)
 
  121        $ilLog = 
$DIC->logger()->root();
 
  126        include_once 
"Services/Cron/classes/class.ilCronJobResult.php";
 
  128        if ($a_job_data === 
null) {
 
  131            $a_job_data = array_pop($jobData);
 
  135        if ($a_job_data[
"alive_ts"]) {
 
  136            $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" still running");
 
  141            if (time() - $a_job_data[
"alive_ts"] > $cut) {
 
  142                $ilDB->manipulate(
"UPDATE cron_job SET" .
 
  143                    " running_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  144                    " , alive_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  145                    " WHERE job_id = " . 
$ilDB->quote($a_job_data[
"job_id"], 
"text"));
 
  152                $result->setMessage(
"Cron job deactivated because it has been inactive for 3 hours");
 
  160                $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" deactivated (assumed crash)");
 
  165            $a_job_data[
"job_result_ts"],
 
  166            $a_job_data[
"schedule_type"],
 
  167            $a_job_data[
"schedule_value"],
 
  170            $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" started");
 
  172            $ilDB->manipulate(
"UPDATE cron_job SET" .
 
  173                " running_ts = " . 
$ilDB->quote(time(), 
"integer") .
 
  174                " , alive_ts = " . 
$ilDB->quote(time(), 
"integer") .
 
  175                " WHERE job_id = " . 
$ilDB->quote($a_job_data[
"job_id"], 
"text"));
 
  180            } 
catch (\Exception 
$e) {
 
  181                $result = new \ilCronJobResult();
 
  183                $result->setMessage(sprintf(
"Exception: %s", 
$e->getMessage()));
 
  185                $ilLog->error(
$e->getMessage());
 
  186                $ilLog->error(
$e->getTraceAsString());
 
  187            } 
catch (\Throwable 
$e) { 
 
  188                $result = new \ilCronJobResult();
 
  190                $result->setMessage(sprintf(
"Exception: %s", 
$e->getMessage()));
 
  192                $ilLog->error(
$e->getMessage());
 
  193                $ilLog->error(
$e->getTraceAsString());
 
  202                $result->setMessage(
"Cron job did not return a proper result");
 
  208                $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" no result");
 
  218                $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" invalid configuration");
 
  229            $ilDB->manipulate(
"UPDATE cron_job SET" .
 
  230                " running_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  231                " , alive_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  232                " WHERE job_id = " . 
$ilDB->quote($a_job_data[
"job_id"], 
"text"));
 
  234            $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" finished");
 
  236            $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] . 
" returned status inactive");
 
  252        $ilLog = 
$DIC->logger()->root();
 
  253        $ilPluginAdmin = 
$DIC[
'ilPluginAdmin'];
 
  256        if (substr($a_job_id, 0, 4) == 
"pl__") {
 
  257            $parts = explode(
"__", $a_job_id);
 
  258            $pl_name = $parts[1];
 
  260            if ($ilPluginAdmin->isActive(
IL_COMP_SERVICE, 
"Cron", 
"crnhk", $pl_name)) {
 
  261                $plugin_obj = $ilPluginAdmin->getPluginObject(
 
  267                $job = $plugin_obj->getCronJobInstance($job_id);
 
  283            $job_data = array_pop($job_data);
 
  284            if ($job_data[
"job_id"] == $a_job_id) {
 
  287                    $job_data[
"component"],
 
  294        $ilLog->write(
"CRON - job " . $a_job_id . 
" seems invalid or is inactive");
 
  305    public static function getJobInstance($a_id, $a_component, $a_class, $a_path = 
null)
 
  309        $ilLog = 
$DIC->logger()->root();
 
  312            $a_path = $a_component . 
"/classes/";
 
  314        $class_file = $a_path . 
"class." . $a_class . 
".php";
 
  315        if (file_exists($class_file)) {
 
  316            include_once $class_file;
 
  317            if (class_exists($a_class)) {
 
  318                $refl = new \ReflectionClass($a_class);
 
  319                $job = $refl->newInstanceWithoutConstructor();
 
  320                if ($refl->isSubclassOf(\ilCronJob::class)) {
 
  321                    if (0 === strlen($job->getId()) || !isset(
$_SERVER[
'PHP_SELF']) || basename(
$_SERVER[
'PHP_SELF']) !== 
'setup.php') {
 
  325                    if ($job->getId() === $a_id) {
 
  328                        $mess .= 
" - job id mismatch";
 
  331                    $mess .= 
" - does not extend ilCronJob";
 
  334                $mess = 
"- class not found in file";
 
  337            $mess = 
" - class file not found";
 
  340        $ilLog->write(
"Cron XML - Job " . $a_id . 
" in class " . $a_class . 
" (" .
 
  341            $class_file . 
") is invalid." . $mess);
 
  359        $ilLog = 
$DIC->logger()->root();
 
  362        if (!isset(
$DIC[
"ilSetting"])) {
 
  363            $DIC[
"ilSetting"] = 
function (
$c) {
 
  371        $sql = 
"SELECT job_id, schedule_type, component, class, path FROM cron_job" .
 
  372            " WHERE job_id = " . 
$ilDB->quote($a_job->
getId(), 
"text");
 
  373        $set = 
$ilDB->query($sql);
 
  374        $row = 
$ilDB->fetchAssoc($set);
 
  375        $job_id = $row[
'job_id'] ?? 
null;
 
  376        $job_exists = ($job_id == $a_job->
getId());
 
  377        $schedule_type = $row[
"schedule_type"] ?? 
null;
 
  380            $row[
'component'] != $a_component ||
 
  381            $row[
'class'] != $a_class ||
 
  382            $row[
'path'] != $a_path
 
  385                'UPDATE cron_job SET component = %s, class = %s, path = %s WHERE job_id = %s',
 
  386                [
'text', 
'text', 
'text', 
'text'],
 
  387                [$a_component, $a_class, $a_path, $a_job->
getId()]
 
  393            $sql = 
"INSERT INTO cron_job (job_id, component, class, path)" .
 
  394                " VALUES (" . 
$ilDB->quote($a_job->
getId(), 
"text") . 
", " .
 
  395                $ilDB->quote($a_component, 
"text") . 
", " .
 
  396                $ilDB->quote($a_class, 
"text") . 
", " .
 
  397                $ilDB->quote($a_path, 
"text") . 
")";
 
  398            $ilDB->manipulate($sql);
 
  400            $ilLog->write(
"Cron XML - Job " . $a_job->
getId() . 
" in class " . $a_class .
 
  412                include_once 
"Services/Administration/classes/class.ilSetting.php";
 
  445    public static function updateFromXML($a_component, $a_id, $a_class, $a_path = 
null)
 
  451        if (!
$ilDB->tableExists(
"cron_job")) {
 
  468    public static function clearFromXML($a_component, array $a_xml_job_ids)
 
  473        $ilLog = 
$DIC->logger()->root();
 
  475        if (!
$ilDB->tableExists(
"cron_job")) {
 
  481        $sql = 
"SELECT job_id FROM cron_job" .
 
  482            " WHERE component = " . 
$ilDB->quote($a_component, 
"text");
 
  483        $set = 
$ilDB->query($sql);
 
  484        while ($row = 
$ilDB->fetchAssoc($set)) {
 
  485            $all_jobs[] = $row[
"job_id"];
 
  488        if (
sizeof($all_jobs)) {
 
  489            if (
sizeof($a_xml_job_ids)) {
 
  491                foreach ($all_jobs as $job_id) {
 
  492                    if (!in_array($job_id, $a_xml_job_ids)) {
 
  493                        $ilDB->manipulate(
"DELETE FROM cron_job" .
 
  494                            " WHERE component = " . 
$ilDB->quote($a_component, 
"text") .
 
  495                            " AND job_id = " . 
$ilDB->quote($job_id, 
"text"));
 
  497                        $ilLog->write(
"Cron XML - Job " . $job_id . 
" in class " . $a_component .
 
  502                $ilDB->manipulate(
"DELETE FROM cron_job" .
 
  503                    " WHERE component = " . 
$ilDB->quote($a_component, 
"text"));
 
  505                $ilLog->write(
"Cron XML - All jobs deleted for " . $a_component . 
" as component is inactive.");
 
  514        $ilPluginAdmin = 
$DIC[
'ilPluginAdmin'];
 
  518        foreach ($ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_SERVICE, 
"Cron", 
"crnhk") as $pl_name) {
 
  519            $plugin_obj = $ilPluginAdmin->getPluginObject(
IL_COMP_SERVICE, 
"Cron", 
"crnhk", $pl_name);
 
  521            foreach ((array) $plugin_obj->getCronJobInstances() as $job) {
 
  523                $item = array_pop($jobData);
 
  524                if (!is_array($item) || 0 === count($item)) {
 
  530                $item = array_pop($jobData);
 
  533                if (!$a_only_active ||
 
  534                    $item[
"job_status"] == 1) {
 
  535                    $res[$job->getId()] = array($job, $item);
 
  557        if ($a_id && !is_array($a_id)) {
 
  558            $a_id = array($a_id);
 
  561        $sql = 
"SELECT * FROM cron_job";
 
  565            $where[] = 
$ilDB->in(
"job_id", $a_id, 
"", 
"text");
 
  569        if (!$a_include_inactive) {
 
  570            $where[] = 
"job_status = " . 
$ilDB->quote(1, 
"integer");
 
  572        if (
sizeof($where)) {
 
  573            $sql .= 
" WHERE " . implode(
" AND ", $where);
 
  577        $sql .= 
" ORDER BY job_id";
 
  579        $set = 
$ilDB->query($sql);
 
  580        while ($row = 
$ilDB->fetchAssoc($set)) {
 
  597        include_once 
"Services/Cron/classes/class.ilCronJobResult.php";
 
  601        $result->setMessage(
"Cron job re-activated by admin");
 
  604        $ilDB->manipulate(
"UPDATE cron_job" .
 
  605            " SET running_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  606            " , alive_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  607            " , job_result_ts = " . 
$ilDB->quote(0, 
"integer") .
 
  608            " WHERE job_id = " . 
$ilDB->quote($a_job->
getId(), 
"text"));
 
  625        if (
$DIC->isDependencyAvailable(
'user')) {
 
  626            $user = 
$DIC->user();
 
  627            $user_id = $a_manual ? $user->getId() : 0;
 
  630        $sql = 
"UPDATE cron_job SET " .
 
  631            " job_status = " . 
$ilDB->quote(1, 
"integer") .
 
  632            " , job_status_user_id = " . 
$ilDB->quote($user_id, 
"integer") .
 
  633            " , job_status_type = " . 
$ilDB->quote($a_manual, 
"integer") .
 
  634            " , job_status_ts = " . 
$ilDB->quote(time(), 
"integer") .
 
  635            " WHERE job_id = " . 
$ilDB->quote($a_job->
getId(), 
"text");
 
  636        $ilDB->manipulate($sql);
 
  653        $user_id = $a_manual ? 
$ilUser->getId() : 0;
 
  655        $sql = 
"UPDATE cron_job SET " .
 
  656            " job_status = " . 
$ilDB->quote(0, 
"integer") .
 
  657            " , job_status_user_id = " . 
$ilDB->quote($user_id, 
"integer") .
 
  658            " , job_status_type = " . 
$ilDB->quote($a_manual, 
"integer") .
 
  659            " , job_status_ts = " . 
$ilDB->quote(time(), 
"integer") .
 
  660            " WHERE job_id = " . 
$ilDB->quote($a_job->
getId(), 
"text");
 
  661        $ilDB->manipulate($sql);
 
  675        if ((
bool) $job[0][
"job_status"]) {
 
  690        if (!(
bool) $job[0][
"job_status"]) {
 
  709        $user_id = $a_manual ? 
$ilUser->getId() : 0;
 
  711        $sql = 
"UPDATE cron_job SET " .
 
  712            " job_result_status = " . 
$ilDB->quote($a_result->
getStatus(), 
"integer") .
 
  713            " , job_result_user_id = " . 
$ilDB->quote($user_id, 
"integer") .
 
  714            " , job_result_code = " . 
$ilDB->quote($a_result->
getCode(), 
"text") .
 
  715            " , job_result_message = " . 
$ilDB->quote($a_result->
getMessage(), 
"text") .
 
  716            " , job_result_type = " . 
$ilDB->quote($a_manual, 
"integer") .
 
  717            " , job_result_ts = " . 
$ilDB->quote(time(), 
"integer") .
 
  718            " , job_result_dur = " . 
$ilDB->quote($a_result->
getDuration() * 1000, 
"integer") .
 
  719            " WHERE job_id = " . 
$ilDB->quote($a_job->
getId(), 
"text");
 
  720        $ilDB->manipulate($sql);
 
  735        if ($a_schedule_type === 
null ||
 
  738            $sql = 
"UPDATE cron_job SET " .
 
  739                " schedule_type = " . 
$ilDB->quote($a_schedule_type, 
"integer") .
 
  740                " , schedule_value = " . 
$ilDB->quote($a_schedule_value, 
"integer") .
 
  741                " WHERE job_id = " . 
$ilDB->quote($a_job->
getId(), 
"text");
 
  742            $ilDB->manipulate($sql);
 
  753        list($usec, $sec) = explode(
" ", microtime());
 
  754        return ((
float) $usec + (
float) $sec);
 
  762    public static function ping($a_job_id)
 
  767        $ilDB->manipulate(
"UPDATE cron_job SET " .
 
  768            " alive_ts = " . 
$ilDB->quote(time(), 
"integer") .
 
  769            " WHERE job_id = " . 
$ilDB->quote($a_job_id, 
"text"));
 
An exception for terminatinating execution or to throw for unit testing.
Cron job result data container.
const CODE_SUPPOSED_CRASH
const STATUS_INVALID_CONFIGURATION
Cron job application base class.
getDefaultScheduleType()
Get schedule type.
activationWasToggled($a_currently_active)
Cron job status was changed.
getDefaultScheduleValue()
Get schedule value.
isActive($a_ts_last_run, $a_schedule_type, $a_schedule_value, $a_manual=false)
Is job currently active?
hasAutoActivation()
Is to be activated on "installation".
hasFlexibleSchedule()
Can the schedule be configured?
getValidScheduleTypes()
Returns a collection of all valid schedule types for a specific job.
static getCronJobData($a_id=null, $a_include_inactive=true)
Get cron job configuration/execution data.
static sendNotification(ilCronJob $a_job, $a_message)
Send notification to admin about job event(s)
static updateFromXML($a_component, $a_id, $a_class, $a_path=null)
Process data from module.xml/service.xml.
static createDefaultEntry(ilCronJob $a_job, $a_component, $a_class, $a_path)
static isJobInactive($a_job_id)
Check if given job is currently inactive.
static getJobInstanceById($a_job_id)
Get job instance (by job id)
static runJobManual($a_job_id)
Run single job manually.
static activateJob(ilCronJob $a_job, $a_manual=false)
Activate cron job.
__construct(\ilSetting $settings, \ilLogger $logger)
ilCronManager constructor.
static getJobInstance($a_id, $a_component, $a_class, $a_path=null)
Get job instance (by job data)
static isJobActive($a_job_id)
Check if given job is currently active.
static deactivateJob(ilCronJob $a_job, $a_manual=false)
Deactivate cron job.
static updateJobResult(ilCronJob $a_job, ilCronJobResult $a_result, $a_manual=false)
Save job result.
static clearFromXML($a_component, array $a_xml_job_ids)
Clear job data.
static resetJob(ilCronJob $a_job)
Reset job.
runActiveJobs()
Run all active jobs.
static ping($a_job_id)
Keep cron job alive.
static updateJobSchedule(ilCronJob $a_job, $a_schedule_type, $a_schedule_value)
Update job schedule.
static runJob(ilCronJob $a_job, array $a_job_data=null, $a_manual=false)
Run single cron job (internal)
static getMicrotime()
Get current microtime.
static getPluginJobs($a_only_active=false)
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date @access public.
static setUseRelativeDates($a_status)
set use relative dates
static useRelativeDates()
check if relative dates are used
@classDescription Date and time handling
Component logger with individual log levels by component id.
static _lookupValue($a_module, $a_keyword)
Class ilStrictCliCronManager.
foreach($_POST as $key=> $value) $res