/** * Executes cron functions for a specific type of plugin. * * @param string $plugintype Plugin type (e.g. 'report') * @param string $description If specified, will display 'Starting (whatever)' * and 'Finished (whatever)' lines, otherwise does not display */ function cron_execute_plugin_type($plugintype, $description = null) { global $DB; // Get list from plugin => function for all plugins $plugins = get_plugin_list_with_function($plugintype, 'cron'); // Modify list for backward compatibility (different files/names) $plugins = cron_bc_hack_plugin_functions($plugintype, $plugins); // Return if no plugins with cron function to process if (!$plugins) { return; } if ($description) { mtrace('Starting ' . $description); } foreach ($plugins as $component => $cronfunction) { $dir = core_component::get_component_directory($component); // Get cron period if specified in version.php, otherwise assume every cron $cronperiod = 0; if (file_exists("{$dir}/version.php")) { $plugin = new stdClass(); include "{$dir}/version.php"; if (isset($plugin->cron)) { $cronperiod = $plugin->cron; } } // Using last cron and cron period, don't run if it already ran recently $lastcron = get_config($component, 'lastcron'); if ($cronperiod && $lastcron) { if ($lastcron + $cronperiod > time()) { // do not execute cron yet continue; } } mtrace('Processing cron function for ' . $component . '...'); cron_trace_time_and_memory(); $pre_dbqueries = $DB->perf_get_queries(); $pre_time = microtime(true); $cronfunction(); mtrace("done. (" . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries, " . round(microtime(true) - $pre_time, 2) . " seconds)"); set_config('lastcron', time(), $component); @set_time_limit(0); } if ($description) { mtrace('Finished ' . $description); } }
/** * Runs the automated backups if required * * @global moodle_database $DB */ public static function run_automated_backup($rundirective = self::RUN_ON_SCHEDULE) { global $CFG, $DB; $status = true; $emailpending = false; $now = time(); $config = get_config('backup'); mtrace("Checking automated backup status", '...'); $state = backup_cron_automated_helper::get_automated_backup_state($rundirective); if ($state === backup_cron_automated_helper::STATE_DISABLED) { mtrace('INACTIVE'); return $state; } else { if ($state === backup_cron_automated_helper::STATE_RUNNING) { mtrace('RUNNING'); if ($rundirective == self::RUN_IMMEDIATELY) { mtrace('Automated backups are already running. If this script is being run by cron this constitues an error. You will need to increase the time between executions within cron.'); } else { mtrace("automated backup are already running. Execution delayed"); } return $state; } else { mtrace('OK'); } } backup_cron_automated_helper::set_state_running(); mtrace("Getting admin info"); $admin = get_admin(); if (!$admin) { mtrace("Error: No admin account was found"); $state = false; } if ($status) { mtrace("Checking courses"); mtrace("Skipping deleted courses", '...'); mtrace(sprintf("%d courses", backup_cron_automated_helper::remove_deleted_courses_from_schedule())); } if ($status) { mtrace('Running required automated backups...'); cron_trace_time_and_memory(); // This could take a while! core_php_time_limit::raise(); raise_memory_limit(MEMORY_EXTRA); $nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup($admin->timezone, $now); $showtime = "undefined"; if ($nextstarttime > 0) { $showtime = date('r', $nextstarttime); } $rs = $DB->get_recordset('course'); foreach ($rs as $course) { $backupcourse = $DB->get_record('backup_courses', array('courseid' => $course->id)); if (!$backupcourse) { $backupcourse = new stdClass(); $backupcourse->courseid = $course->id; $backupcourse->laststatus = self::BACKUP_STATUS_NOTYETRUN; $DB->insert_record('backup_courses', $backupcourse); $backupcourse = $DB->get_record('backup_courses', array('courseid' => $course->id)); } // The last backup is considered as successful when OK or SKIPPED. $lastbackupwassuccessful = ($backupcourse->laststatus == self::BACKUP_STATUS_SKIPPED || $backupcourse->laststatus == self::BACKUP_STATUS_OK) && ($backupcourse->laststarttime > 0 && $backupcourse->lastendtime > 0); // Assume that we are not skipping anything. $skipped = false; $skippedmessage = ''; // Check if we are going to be running the backup now. $shouldrunnow = $backupcourse->nextstarttime > 0 && $backupcourse->nextstarttime < $now || $rundirective == self::RUN_IMMEDIATELY; // If config backup_auto_skip_hidden is set to true, skip courses that are not visible. if ($shouldrunnow && $config->backup_auto_skip_hidden) { $skipped = $config->backup_auto_skip_hidden && !$course->visible; $skippedmessage = 'Not visible'; } // If config backup_auto_skip_modif_days is set to true, skip courses // that have not been modified since the number of days defined. if ($shouldrunnow && !$skipped && $lastbackupwassuccessful && $config->backup_auto_skip_modif_days) { $timenotmodifsincedays = $now - $config->backup_auto_skip_modif_days * DAYSECS; // Check log if there were any modifications to the course content. $logexists = self::is_course_modified($course->id, $timenotmodifsincedays); $skipped = $course->timemodified <= $timenotmodifsincedays && !$logexists; $skippedmessage = 'Not modified in the past ' . $config->backup_auto_skip_modif_days . ' days'; } // If config backup_auto_skip_modif_prev is set to true, skip courses // that have not been modified since previous backup. if ($shouldrunnow && !$skipped && $lastbackupwassuccessful && $config->backup_auto_skip_modif_prev) { // Check log if there were any modifications to the course content. $logexists = self::is_course_modified($course->id, $backupcourse->laststarttime); $skipped = $course->timemodified <= $backupcourse->laststarttime && !$logexists; $skippedmessage = 'Not modified since previous backup'; } // Check if the course is not scheduled to run right now. if (!$shouldrunnow) { $backupcourse->nextstarttime = $nextstarttime; $DB->update_record('backup_courses', $backupcourse); mtrace('Skipping ' . $course->fullname . ' (Not scheduled for backup until ' . $showtime . ')'); } else { if ($skipped) { // Must have been skipped for a reason. $backupcourse->laststatus = self::BACKUP_STATUS_SKIPPED; $backupcourse->nextstarttime = $nextstarttime; $DB->update_record('backup_courses', $backupcourse); mtrace('Skipping ' . $course->fullname . ' (' . $skippedmessage . ')'); mtrace('Backup of \'' . $course->fullname . '\' is scheduled on ' . $showtime); } else { // Backup every non-skipped courses. mtrace('Backing up ' . $course->fullname . '...'); // We have to send an email because we have included at least one backup. $emailpending = true; // Only make the backup if laststatus isn't 2-UNFINISHED (uncontrolled error). if ($backupcourse->laststatus != self::BACKUP_STATUS_UNFINISHED) { // Set laststarttime. $starttime = time(); $backupcourse->laststarttime = time(); $backupcourse->laststatus = self::BACKUP_STATUS_UNFINISHED; $DB->update_record('backup_courses', $backupcourse); $backupcourse->laststatus = backup_cron_automated_helper::launch_automated_backup($course, $backupcourse->laststarttime, $admin->id); $backupcourse->lastendtime = time(); $backupcourse->nextstarttime = $nextstarttime; $DB->update_record('backup_courses', $backupcourse); if ($backupcourse->laststatus === self::BACKUP_STATUS_OK) { // Clean up any excess course backups now that we have // taken a successful backup. $removedcount = backup_cron_automated_helper::remove_excess_backups($course); } } mtrace("complete - next execution: {$showtime}"); } } } $rs->close(); } //Send email to admin if necessary if ($emailpending) { mtrace("Sending email to admin"); $message = ""; $count = backup_cron_automated_helper::get_backup_status_array(); $haserrors = $count[self::BACKUP_STATUS_ERROR] != 0 || $count[self::BACKUP_STATUS_UNFINISHED] != 0; // Build the message text. // Summary. $message .= get_string('summary') . "\n"; $message .= "==================================================\n"; $message .= ' ' . get_string('courses') . '; ' . array_sum($count) . "\n"; $message .= ' ' . get_string('ok') . '; ' . $count[self::BACKUP_STATUS_OK] . "\n"; $message .= ' ' . get_string('skipped') . '; ' . $count[self::BACKUP_STATUS_SKIPPED] . "\n"; $message .= ' ' . get_string('error') . '; ' . $count[self::BACKUP_STATUS_ERROR] . "\n"; $message .= ' ' . get_string('unfinished') . '; ' . $count[self::BACKUP_STATUS_UNFINISHED] . "\n"; $message .= ' ' . get_string('warning') . '; ' . $count[self::BACKUP_STATUS_WARNING] . "\n"; $message .= ' ' . get_string('backupnotyetrun') . '; ' . $count[self::BACKUP_STATUS_NOTYETRUN] . "\n\n"; //Reference if ($haserrors) { $message .= " " . get_string('backupfailed') . "\n\n"; $dest_url = "{$CFG->wwwroot}/report/backups/index.php"; $message .= " " . get_string('backuptakealook', '', $dest_url) . "\n\n"; //Set message priority $admin->priority = 1; //Reset unfinished to error $DB->set_field('backup_courses', 'laststatus', '0', array('laststatus' => '2')); } else { $message .= " " . get_string('backupfinished') . "\n"; } //Build the message subject $site = get_site(); $prefix = format_string($site->shortname, true, array('context' => context_course::instance(SITEID))) . ": "; if ($haserrors) { $prefix .= "[" . strtoupper(get_string('error')) . "] "; } $subject = $prefix . get_string('automatedbackupstatus', 'backup'); //Send the message $eventdata = new stdClass(); $eventdata->modulename = 'moodle'; $eventdata->userfrom = $admin; $eventdata->userto = $admin; $eventdata->subject = $subject; $eventdata->fullmessage = $message; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = ''; $eventdata->component = 'moodle'; $eventdata->name = 'backup'; message_send($eventdata); } //Everything is finished stop backup_auto_running backup_cron_automated_helper::set_state_running(false); mtrace('Automated backups complete.'); return $status; }
/** * Update calendar subscriptions. * * @return bool */ function calendar_cron() { global $CFG, $DB; // In order to execute this we need bennu. require_once $CFG->libdir . '/bennu/bennu.inc.php'; mtrace('Updating calendar subscriptions:'); cron_trace_time_and_memory(); $time = time(); $subscriptions = $DB->get_records_sql('SELECT * FROM {event_subscriptions} WHERE pollinterval > 0 AND lastupdated + pollinterval < ?', array($time)); foreach ($subscriptions as $sub) { mtrace("Updating calendar subscription {$sub->name} in course {$sub->courseid}"); try { $log = calendar_update_subscription_events($sub->id); mtrace(trim(strip_tags($log))); } catch (moodle_exception $ex) { mtrace('Error updating calendar subscription: ' . $ex->getMessage()); } } mtrace('Finished updating calendar subscriptions.'); return true; }
/** * Cron cleanup job. */ public function cron() { global $CFG, $DB; require_once $CFG->libdir . '/cronlib.php'; // find out all stale draft areas (older than 4 days) and purge them // those are identified by time stamp of the /. root dir mtrace('Deleting old draft files... ', ''); cron_trace_time_and_memory(); $old = time() - 60 * 60 * 24 * 4; $sql = "SELECT *\n FROM {files}\n WHERE component = 'user' AND filearea = 'draft' AND filepath = '/' AND filename = '.'\n AND timecreated < :old"; $rs = $DB->get_recordset_sql($sql, array('old' => $old)); foreach ($rs as $dir) { $this->delete_area_files($dir->contextid, $dir->component, $dir->filearea, $dir->itemid); } $rs->close(); mtrace('done.'); // remove orphaned preview files (that is files in the core preview filearea without // the existing original file) mtrace('Deleting orphaned preview files... ', ''); cron_trace_time_and_memory(); $sql = "SELECT p.*\n FROM {files} p\n LEFT JOIN {files} o ON (p.filename = o.contenthash)\n WHERE p.contextid = ? AND p.component = 'core' AND p.filearea = 'preview' AND p.itemid = 0\n AND o.id IS NULL"; $syscontext = context_system::instance(); $rs = $DB->get_recordset_sql($sql, array($syscontext->id)); foreach ($rs as $orphan) { $file = $this->get_file_instance($orphan); if (!$file->is_directory()) { $file->delete(); } } $rs->close(); mtrace('done.'); // Remove orphaned converted files (that is files in the core documentconversion filearea without // the existing original file). mtrace('Deleting orphaned document conversion files... ', ''); cron_trace_time_and_memory(); $sql = "SELECT p.*\n FROM {files} p\n LEFT JOIN {files} o ON (p.filename = o.contenthash)\n WHERE p.contextid = ? AND p.component = 'core' AND p.filearea = 'documentconversion' AND p.itemid = 0\n AND o.id IS NULL"; $syscontext = context_system::instance(); $rs = $DB->get_recordset_sql($sql, array($syscontext->id)); foreach ($rs as $orphan) { $file = $this->get_file_instance($orphan); if (!$file->is_directory()) { $file->delete(); } } $rs->close(); mtrace('done.'); // remove trash pool files once a day // if you want to disable purging of trash put $CFG->fileslastcleanup=time(); into config.php if (empty($CFG->fileslastcleanup) or $CFG->fileslastcleanup < time() - 60 * 60 * 24) { require_once $CFG->libdir . '/filelib.php'; // Delete files that are associated with a context that no longer exists. mtrace('Cleaning up files from deleted contexts... ', ''); cron_trace_time_and_memory(); $sql = "SELECT DISTINCT f.contextid\n FROM {files} f\n LEFT OUTER JOIN {context} c ON f.contextid = c.id\n WHERE c.id IS NULL"; $rs = $DB->get_recordset_sql($sql); if ($rs->valid()) { $fs = get_file_storage(); foreach ($rs as $ctx) { $fs->delete_area_files($ctx->contextid); } } $rs->close(); mtrace('done.'); mtrace('Deleting trash files... ', ''); cron_trace_time_and_memory(); fulldelete($this->trashdir); set_config('fileslastcleanup', time()); mtrace('done.'); } }
/** * used by admin/cron.php to get similarity scores from submitted files. * */ function plagiarism_cron() { global $CFG; if (empty($CFG->enableplagiarism)) { return ''; } $plagiarismplugins = plagiarism_load_available_plugins(); foreach ($plagiarismplugins as $plugin => $dir) { mtrace('Processing cron function for plagiarism_plugin_' . $plugin . '...', ''); cron_trace_time_and_memory(); require_once $dir . '/lib.php'; $plagiarismclass = "plagiarism_plugin_{$plugin}"; $plagiarismplugin = new $plagiarismclass(); $plagiarismplugin->cron(); } }
/** * Remove old stats data */ function stats_clean_old() { global $DB; mtrace("Running stats cleanup tasks..."); cron_trace_time_and_memory(); $deletebefore = stats_get_base_monthly(); // delete dailies older than 3 months (to be safe) $deletebefore = strtotime('-3 months', $deletebefore); $DB->delete_records_select('stats_daily', "timeend < {$deletebefore}"); $DB->delete_records_select('stats_user_daily', "timeend < {$deletebefore}"); // delete weeklies older than 9 months (to be safe) $deletebefore = strtotime('-6 months', $deletebefore); $DB->delete_records_select('stats_weekly', "timeend < {$deletebefore}"); $DB->delete_records_select('stats_user_weekly', "timeend < {$deletebefore}"); // don't delete monthlies mtrace("...stats cleanup finished"); }
if ($input == 'n') { mtrace('exited'); exit; } } set_time_limit(0); $starttime = microtime(); // Increase memory limit raise_memory_limit(MEMORY_EXTRA); // Emulate normal session - we use admin accoutn by default cron_setup_user(); // Start output log $timenow = time(); mtrace("Server Time: " . date('r', $timenow) . "\n\n"); mtrace("Processing Dialogue module cron ...", ''); cron_trace_time_and_memory(); $pre_dbqueries = null; $pre_dbqueries = $DB->perf_get_queries(); $pre_time = microtime(1); // Process bulk open rules dialogue_process_bulk_openrules(); if (isset($pre_dbqueries)) { mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pre_time) . " seconds"); } // Reset possible changes by modules to time_limit. MDL-11597 @set_time_limit(0); mtrace("done."); gc_collect_cycles(); mtrace('Cron completed at ' . date('H:i:s') . '. Memory used ' . display_size(memory_get_usage()) . '.'); $difftime = microtime_diff($starttime, microtime());