Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace quiz_statistics\task;
  18  
  19  use core\dml\sql_join;
  20  use quiz_attempt;
  21  use quiz_statistics_report;
  22  
  23  defined('MOODLE_INTERNAL') || die();
  24  
  25  require_once($CFG->dirroot . '/mod/quiz/locallib.php');
  26  require_once($CFG->dirroot . '/mod/quiz/report/statistics/statisticslib.php');
  27  require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
  28  require_once($CFG->dirroot . '/mod/quiz/report/statistics/report.php');
  29  
  30  /**
  31   * Re-calculate question statistics.
  32   *
  33   * @package    quiz_statistics
  34   * @copyright  2022 Catalyst IT Australia Pty Ltd
  35   * @author     Nathan Nguyen <nathannguyen@catalyst-au.net>
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class recalculate extends \core\task\adhoc_task {
  39      /**
  40       * The time to delay queued runs by, to prevent repeated recalculations.
  41       */
  42      const DELAY = HOURSECS;
  43  
  44      /**
  45       * Create a new instance of the task.
  46       *
  47       * This sets the properties so that only one task will be queued at a time for a given quiz.
  48       *
  49       * @param int $quizid
  50       * @return recalculate
  51       */
  52      public static function instance(int $quizid): recalculate {
  53          $task = new self();
  54          $task->set_component('quiz_statistics');
  55          $task->set_custom_data((object)[
  56              'quizid' => $quizid,
  57          ]);
  58          return $task;
  59      }
  60  
  61  
  62      public function get_name(): string {
  63          return get_string('recalculatetask', 'quiz_statistics');
  64      }
  65  
  66      public function execute(): void {
  67          global $DB;
  68          $dateformat = get_string('strftimedatetimeshortaccurate', 'core_langconfig');
  69          $data = $this->get_custom_data();
  70          $quiz = $DB->get_record('quiz', ['id' => $data->quizid]);
  71          if (!$quiz) {
  72              mtrace('Could not find quiz with ID ' . $data->quizid . '.');
  73              return;
  74          }
  75          $course = $DB->get_record('course', ['id' => $quiz->course]);
  76          if (!$course) {
  77              mtrace('Could not find course with ID ' . $quiz->course . '.');
  78              return;
  79          }
  80          $attemptcount = $DB->count_records('quiz_attempts', ['quiz' => $data->quizid, 'state' => quiz_attempt::FINISHED]);
  81          if ($attemptcount === 0) {
  82              mtrace('Could not find any finished attempts for course with ID ' . $data->quizid . '.');
  83              return;
  84          }
  85  
  86          mtrace("Re-calculating statistics for quiz {$quiz->name} ({$quiz->id}) " .
  87              "from course {$course->shortname} ({$course->id}) with {$attemptcount} attempts, start time " .
  88              userdate(time(), $dateformat) . " ...");
  89  
  90          $qubaids = quiz_statistics_qubaids_condition(
  91              $quiz->id,
  92              new sql_join(),
  93              $quiz->grademethod
  94          );
  95  
  96          $report = new quiz_statistics_report();
  97          $report->clear_cached_data($qubaids);
  98          $report->calculate_questions_stats_for_question_bank($quiz->id);
  99          mtrace('    Calculations completed at ' . userdate(time(), $dateformat) . '.');
 100      }
 101  
 102      /**
 103       * Queue an instance of this task to happen after a delay.
 104       *
 105       * Multiple events may happen over a short period that require a recalculation. Rather than
 106       * run the recalculation each time, this will queue a single run of the task for a given quiz,
 107       * within the delay period.
 108       *
 109       * @param int $quizid The quiz to run the recalculation for.
 110       * @return bool true of the task was queued.
 111       */
 112      public static function queue_future_run(int $quizid): bool {
 113          $task = self::instance($quizid);
 114          $task->set_next_run_time(time() + self::DELAY);
 115          return \core\task\manager::queue_adhoc_task($task, true);
 116      }
 117  }