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 310 and 401] [Versions 311 and 401] [Versions 39 and 401]

   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   * Matching question renderer class.
  19   *
  20   * @package   qtype_match
  21   * @copyright 2009 The Open University
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  
  29  /**
  30   * Generates the output for matching questions.
  31   *
  32   * @copyright 2009 The Open University
  33   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  class qtype_match_renderer extends qtype_with_combined_feedback_renderer {
  36  
  37      public function formulation_and_controls(question_attempt $qa,
  38              question_display_options $options) {
  39  
  40          $question = $qa->get_question();
  41          $stemorder = $question->get_stem_order();
  42          $response = $qa->get_last_qt_data();
  43  
  44          $choices = $this->format_choices($question);
  45  
  46          $result = '';
  47          $result .= html_writer::tag('div', $question->format_questiontext($qa),
  48                  array('class' => 'qtext'));
  49  
  50          $result .= html_writer::start_tag('div', array('class' => 'ablock'));
  51          $result .= html_writer::start_tag('table', array('class' => 'answer'));
  52          $result .= html_writer::start_tag('tbody');
  53  
  54          $parity = 0;
  55          $i = 1;
  56          foreach ($stemorder as $key => $stemid) {
  57  
  58              $result .= html_writer::start_tag('tr', array('class' => 'r' . $parity));
  59              $fieldname = 'sub' . $key;
  60  
  61              $result .= html_writer::tag('td', $this->format_stem_text($qa, $stemid),
  62                      array('class' => 'text'));
  63  
  64              $classes = 'control';
  65              $feedbackimage = '';
  66  
  67              if (array_key_exists($fieldname, $response)) {
  68                  $selected = $response[$fieldname];
  69              } else {
  70                  $selected = 0;
  71              }
  72  
  73              $fraction = (int) ($selected && $selected == $question->get_right_choice_for($stemid));
  74  
  75              if ($options->correctness && $selected) {
  76                  $classes .= ' ' . $this->feedback_class($fraction);
  77                  $feedbackimage = $this->feedback_image($fraction);
  78              }
  79  
  80              $labeltext = $options->add_question_identifier_to_label(get_string('answer', 'qtype_match', $i));
  81              $result .= html_writer::tag('td',
  82                      html_writer::label($labeltext,
  83                              'menu' . $qa->get_qt_field_name('sub' . $key), false,
  84                              array('class' => 'accesshide')) .
  85                      html_writer::select($choices, $qa->get_qt_field_name('sub' . $key), $selected,
  86                              array('0' => 'choose'), array('disabled' => $options->readonly, 'class' => 'custom-select ml-1')) .
  87                      ' ' . $feedbackimage, array('class' => $classes));
  88  
  89              $result .= html_writer::end_tag('tr');
  90              $parity = 1 - $parity;
  91              $i++;
  92          }
  93          $result .= html_writer::end_tag('tbody');
  94          $result .= html_writer::end_tag('table');
  95  
  96          $result .= html_writer::end_tag('div'); // Closes <div class="ablock">.
  97  
  98          if ($qa->get_state() == question_state::$invalid) {
  99              $result .= html_writer::nonempty_tag('div',
 100                      $question->get_validation_error($response),
 101                      array('class' => 'validationerror'));
 102          }
 103  
 104          return $result;
 105      }
 106  
 107      public function specific_feedback(question_attempt $qa) {
 108          return $this->combined_feedback($qa);
 109      }
 110  
 111      /**
 112       * Format each question stem. Overwritten by randomsamatch renderer.
 113       *
 114       * @param question_attempt $qa
 115       * @param integer $stemid stem index
 116       * @return string
 117       */
 118      public function format_stem_text($qa, $stemid) {
 119          $question = $qa->get_question();
 120          return $question->format_text(
 121                      $question->stems[$stemid], $question->stemformat[$stemid],
 122                      $qa, 'qtype_match', 'subquestion', $stemid);
 123      }
 124  
 125      protected function format_choices($question) {
 126          $choices = array();
 127          foreach ($question->get_choice_order() as $key => $choiceid) {
 128              $choices[$key] = format_string($question->choices[$choiceid]);
 129          }
 130          return $choices;
 131      }
 132  
 133      public function correct_response(question_attempt $qa) {
 134          $question = $qa->get_question();
 135          $stemorder = $question->get_stem_order();
 136  
 137          $choices = $this->format_choices($question);
 138          $right = array();
 139          foreach ($stemorder as $key => $stemid) {
 140              if (!isset($choices[$question->get_right_choice_for($stemid)])) {
 141                  continue;
 142              }
 143              $right[] = $question->make_html_inline($this->format_stem_text($qa, $stemid)) . ' &#x2192; ' .
 144                      $choices[$question->get_right_choice_for($stemid)];
 145          }
 146  
 147          if (!empty($right)) {
 148              return get_string('correctansweris', 'qtype_match', implode(', ', $right));
 149          }
 150      }
 151  }