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 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  /**
  18   * This file defines the quiz responses report class.
  19   *
  20   * @package   quiz_responses
  21   * @copyright 2006 Jean-Michel Vedrine
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  require_once($CFG->dirroot . '/mod/quiz/report/attemptsreport.php');
  29  require_once($CFG->dirroot . '/mod/quiz/report/responses/responses_options.php');
  30  require_once($CFG->dirroot . '/mod/quiz/report/responses/responses_form.php');
  31  require_once($CFG->dirroot . '/mod/quiz/report/responses/last_responses_table.php');
  32  require_once($CFG->dirroot . '/mod/quiz/report/responses/first_or_all_responses_table.php');
  33  
  34  
  35  /**
  36   * Quiz report subclass for the responses report.
  37   *
  38   * This report lists some combination of
  39   *  * what question each student saw (this makes sense if random questions were used).
  40   *  * the response they gave,
  41   *  * and what the right answer is.
  42   *
  43   * Like the overview report, there are options for showing students with/without
  44   * attempts, and for deleting selected attempts.
  45   *
  46   * @copyright 1999 onwards Martin Dougiamas and others {@link http://moodle.com}
  47   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  48   */
  49  class quiz_responses_report extends quiz_attempts_report {
  50  
  51      public function display($quiz, $cm, $course) {
  52          global $OUTPUT, $DB;
  53  
  54          list($currentgroup, $studentsjoins, $groupstudentsjoins, $allowedjoins) = $this->init(
  55                  'responses', 'quiz_responses_settings_form', $quiz, $cm, $course);
  56  
  57          $options = new quiz_responses_options('responses', $quiz, $cm, $course);
  58  
  59          if ($fromform = $this->form->get_data()) {
  60              $options->process_settings_from_form($fromform);
  61  
  62          } else {
  63              $options->process_settings_from_params();
  64          }
  65  
  66          $this->form->set_data($options->get_initial_form_data());
  67  
  68          // Load the required questions.
  69          $questions = quiz_report_get_significant_questions($quiz);
  70  
  71          // Prepare for downloading, if applicable.
  72          $courseshortname = format_string($course->shortname, true,
  73                  array('context' => context_course::instance($course->id)));
  74          if ($options->whichtries === question_attempt::LAST_TRY) {
  75              $tableclassname = 'quiz_last_responses_table';
  76          } else {
  77              $tableclassname = 'quiz_first_or_all_responses_table';
  78          }
  79          $table = new $tableclassname($quiz, $this->context, $this->qmsubselect,
  80                  $options, $groupstudentsjoins, $studentsjoins, $questions, $options->get_url());
  81          $filename = quiz_report_download_filename(get_string('responsesfilename', 'quiz_responses'),
  82                  $courseshortname, $quiz->name);
  83          $table->is_downloading($options->download, $filename,
  84                  $courseshortname . ' ' . format_string($quiz->name, true));
  85          if ($table->is_downloading()) {
  86              raise_memory_limit(MEMORY_EXTRA);
  87          }
  88  
  89          $this->hasgroupstudents = false;
  90          if (!empty($groupstudentsjoins->joins)) {
  91              $sql = "SELECT DISTINCT u.id
  92                        FROM {user} u
  93                      $groupstudentsjoins->joins
  94                       WHERE $groupstudentsjoins->wheres";
  95              $this->hasgroupstudents = $DB->record_exists_sql($sql, $groupstudentsjoins->params);
  96          }
  97          $hasstudents = false;
  98          if (!empty($studentsjoins->joins)) {
  99              $sql = "SELECT DISTINCT u.id
 100                      FROM {user} u
 101                      $studentsjoins->joins
 102                      WHERE $studentsjoins->wheres";
 103              $hasstudents = $DB->record_exists_sql($sql, $studentsjoins->params);
 104          }
 105          if ($options->attempts == self::ALL_WITH) {
 106              // This option is only available to users who can access all groups in
 107              // groups mode, so setting allowed to empty (which means all quiz attempts
 108              // are accessible, is not a security problem.
 109              $allowedjoins = new \core\dml\sql_join();
 110          }
 111  
 112          $this->process_actions($quiz, $cm, $currentgroup, $groupstudentsjoins, $allowedjoins, $options->get_url());
 113  
 114          $hasquestions = quiz_has_questions($quiz->id);
 115  
 116          // Start output.
 117          if (!$table->is_downloading()) {
 118              // Only print headers if not asked to download data.
 119              $this->print_standard_header_and_messages($cm, $course, $quiz,
 120                      $options, $currentgroup, $hasquestions, $hasstudents);
 121  
 122              // Print the display options.
 123              $this->form->display();
 124          }
 125  
 126          $hasstudents = $hasstudents && (!$currentgroup || $this->hasgroupstudents);
 127          if ($hasquestions && ($hasstudents || $options->attempts == self::ALL_WITH)) {
 128  
 129              $table->setup_sql_queries($allowedjoins);
 130  
 131              if (!$table->is_downloading()) {
 132                  // Print information on the grading method.
 133                  if ($strattempthighlight = quiz_report_highlighting_grading_method(
 134                          $quiz, $this->qmsubselect, $options->onlygraded)) {
 135                      echo '<div class="quizattemptcounts">' . $strattempthighlight . '</div>';
 136                  }
 137              }
 138  
 139              // Define table columns.
 140              $columns = array();
 141              $headers = array();
 142  
 143              if (!$table->is_downloading() && $options->checkboxcolumn) {
 144                  $columnname = 'checkbox';
 145                  $columns[] = $columnname;
 146                  $headers[] = $table->checkbox_col_header($columnname);
 147              }
 148  
 149              $this->add_user_columns($table, $columns, $headers);
 150              $this->add_state_column($columns, $headers);
 151  
 152              if ($table->is_downloading()) {
 153                  $this->add_time_columns($columns, $headers);
 154              }
 155  
 156              $this->add_grade_columns($quiz, $options->usercanseegrades, $columns, $headers);
 157  
 158              foreach ($questions as $id => $question) {
 159                  if ($options->showqtext) {
 160                      $columns[] = 'question' . $id;
 161                      $headers[] = get_string('questionx', 'question', $question->number);
 162                  }
 163                  if ($options->showresponses) {
 164                      $columns[] = 'response' . $id;
 165                      $headers[] = get_string('responsex', 'quiz_responses', $question->number);
 166                  }
 167                  if ($options->showright) {
 168                      $columns[] = 'right' . $id;
 169                      $headers[] = get_string('rightanswerx', 'quiz_responses', $question->number);
 170                  }
 171              }
 172  
 173              $table->define_columns($columns);
 174              $table->define_headers($headers);
 175              $table->sortable(true, 'uniqueid');
 176  
 177              // Set up the table.
 178              $table->define_baseurl($options->get_url());
 179  
 180              $this->configure_user_columns($table);
 181  
 182              $table->no_sorting('feedbacktext');
 183              $table->column_class('sumgrades', 'bold');
 184  
 185              $table->set_attribute('id', 'responses');
 186  
 187              $table->collapsible(true);
 188  
 189              $table->out($options->pagesize, true);
 190          }
 191          return true;
 192      }
 193  }