MDL-61800 task: Reset the OUTPUT and PAGE on execution
authorAndrew Nicols <andrew@nicols.co.uk>
Wed, 2 May 2018 03:40:08 +0000 (11:40 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Wed, 2 May 2018 03:57:13 +0000 (11:57 +0800)
lib/cronlib.php
lib/upgrade.txt

index 4ce1c69..589af74 100644 (file)
@@ -101,6 +101,7 @@ function cron_run_inner_scheduled_task(\core\task\task_base $task) {
     $pretime = microtime(1);
     try {
         get_mailer('buffer');
+        cron_prepare_core_renderer();
         $task->execute();
         if ($DB->is_transaction_started()) {
             throw new coding_exception("Task left transaction open");
@@ -130,6 +131,8 @@ function cron_run_inner_scheduled_task(\core\task\task_base $task) {
             mtrace(format_backtrace($e->getTrace(), true));
         }
         \core\task\manager::scheduled_task_failed($task);
+    } finally {
+        cron_prepare_core_renderer(true);
     }
     get_mailer('close');
 }
@@ -178,6 +181,7 @@ function cron_run_inner_adhoc_task(\core\task\adhoc_task $task) {
 
     try {
         get_mailer('buffer');
+        cron_prepare_core_renderer();
         $task->execute();
         if ($DB->is_transaction_started()) {
             throw new coding_exception("Task left transaction open");
@@ -210,6 +214,7 @@ function cron_run_inner_adhoc_task(\core\task\adhoc_task $task) {
     } finally {
         // Reset back to the standard admin user.
         cron_setup_user();
+        cron_prepare_core_renderer(true);
     }
     get_mailer('close');
 }
@@ -433,3 +438,43 @@ function cron_bc_hack_plugin_functions($plugintype, $plugins) {
 
     return $plugins;
 }
+
+/**
+ * Prepare the output renderer for the cron run.
+ *
+ * This involves creating a new $PAGE, and $OUTPUT fresh for each task and prevents any one task from influencing
+ * any other.
+ *
+ * @param   bool    $restore Whether to restore the original PAGE and OUTPUT
+ */
+function cron_prepare_core_renderer($restore = false) {
+    global $OUTPUT, $PAGE;
+
+    // Store the original PAGE and OUTPUT values so that they can be reset at a later point to the original.
+    // This should not normally be required, but may be used in places such as the scheduled task tool's "Run now"
+    // functionality.
+    static $page = null;
+    static $output = null;
+
+    if (null === $page) {
+        $page = $PAGE;
+    }
+
+    if (null === $output) {
+        $output = $OUTPUT;
+    }
+
+    if (!empty($restore)) {
+        $PAGE = $page;
+        $page = null;
+
+        $OUTPUT = $output;
+        $output = null;
+    } else {
+        // Setup a new General renderer.
+        // Cron tasks may produce output to be used in web, so we must use the appropriate renderer target.
+        // This allows correct use of templates, etc.
+        $PAGE = new \moodle_page();
+        $OUTPUT = new \core_renderer($PAGE, RENDERER_TARGET_GENERAL);
+    }
+}
index c569cf6..54f8dec 100644 (file)
@@ -3,6 +3,7 @@ information provided here is intended especially for developers.
 
 === 3.5 ===
 
+* The cron runner now sets up a fresh PAGE and OUTPUT between each task.
 * The core_renderer methods notify_problem(), notify_success(), notify_message() and notify_redirect() that were
   deprecated in Moodle 3.1 have been removed. Use \core\notification::add(), or \core\output\notification as required.
 * The maximum supported precision (the total number of digits) for XMLDB_TYPE_NUMBER ("number") fields raised from 20 to