Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   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   * Upgrade library code for the multianswer question type.
  19   *
  20   * @package    qtype
  21   * @subpackage multianswer
  22   * @copyright  2011 The Open University
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  
  30  /**
  31   * Class for converting attempt data for multianswer questions when upgrading
  32   * attempts to the new question engine.
  33   *
  34   * This class is used by the code in question/engine/upgrade/upgradelib.php.
  35   *
  36   * @copyright  2011 The Open University
  37   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   */
  39  class qtype_multianswer_qe2_attempt_updater extends question_qtype_attempt_updater {
  40  
  41      public function question_summary() {
  42          $summary = $this->to_text($this->question->questiontext);
  43          foreach ($this->question->options->questions as $i => $subq) {
  44              switch ($subq->qtype) {
  45                  case 'multichoice':
  46                      $choices = array();
  47                      foreach ($subq->options->answers as $ans) {
  48                          $choices[] = $this->to_text($ans->answer);
  49                      }
  50                      $answerbit = '{' . implode('; ', $choices) . '}';
  51                      break;
  52                  case 'numerical':
  53                  case 'shortanswer':
  54                      $answerbit = '_____';
  55                      break;
  56                  default:
  57                      $answerbit = '{ERR unknown sub-question type}';
  58              }
  59              $summary = str_replace('{#' . $i . '}', $answerbit, $summary);
  60          }
  61          return $summary;
  62      }
  63  
  64      public function right_answer() {
  65          $right = array();
  66  
  67          foreach ($this->question->options->questions as $i => $subq) {
  68              foreach ($subq->options->answers as $ans) {
  69                  if ($ans->fraction > 0.999) {
  70                      $right[$i] = $ans->answer;
  71                      break;
  72                  }
  73              }
  74          }
  75  
  76          return $this->display_response($right);
  77      }
  78  
  79      public function explode_answer($answer) {
  80          $response = array();
  81  
  82          foreach (explode(',', $answer) as $part) {
  83              list($index, $partanswer) = explode('-', $part, 2);
  84              $response[$index] = str_replace(
  85                      array('&#0044;', '&#0045;'), array(",", "-"), $partanswer);
  86          }
  87  
  88          return $response;
  89      }
  90  
  91      public function display_response($response) {
  92          $summary = array();
  93          foreach ($this->question->options->questions as $i => $subq) {
  94              $a = new stdClass();
  95              $a->i = $i;
  96              $a->response = $this->to_text($response[$i]);
  97              $summary[] = get_string('subqresponse', 'qtype_multianswer', $a);
  98          }
  99  
 100          return implode('; ', $summary);
 101      }
 102  
 103      public function response_summary($state) {
 104          $response = $this->explode_answer($state->answer);
 105          foreach ($this->question->options->questions as $i => $subq) {
 106              if ($response[$i] && $subq->qtype == 'multichoice') {
 107                  $response[$i] = $subq->options->answers[$response[$i]]->answer;
 108              }
 109          }
 110          return $this->display_response($response);
 111      }
 112  
 113      public function was_answered($state) {
 114          return !empty($state->answer);
 115      }
 116  
 117      public function set_first_step_data_elements($state, &$data) {
 118          foreach ($this->question->options->questions as $i => $subq) {
 119              switch ($subq->qtype) {
 120                  case 'multichoice':
 121                      $data[$this->add_prefix('_order', $i)] =
 122                              implode(',', array_keys($subq->options->answers));
 123                      break;
 124                  case 'numerical':
 125                      $data[$this->add_prefix('_separators', $i)] = '.$,';
 126                      break;
 127              }
 128          }
 129      }
 130  
 131      public function supply_missing_first_step_data(&$data) {
 132      }
 133  
 134      public function set_data_elements_for_step($state, &$data) {
 135          $response = $this->explode_answer($state->answer);
 136          foreach ($this->question->options->questions as $i => $subq) {
 137              if (empty($response[$i])) {
 138                  continue;
 139              }
 140  
 141              switch ($subq->qtype) {
 142                  case 'multichoice':
 143                      $choices = array();
 144                      $order = 0;
 145                      foreach ($subq->options->answers as $ans) {
 146                          if ($ans->id == $response[$i]) {
 147                              $data[$this->add_prefix('answer', $i)] = $order;
 148                          }
 149                          $order++;
 150                      }
 151                      $answerbit = '{' . implode('; ', $choices) . '}';
 152                      break;
 153                  case 'numerical':
 154                  case 'shortanswer':
 155                      $data[$this->add_prefix('answer', $i)] = $response[$i];
 156                      break;
 157              }
 158          }
 159      }
 160  
 161      public function add_prefix($field, $i) {
 162          $prefix = 'sub' . $i . '_';
 163          if (substr($field, 0, 2) === '!_') {
 164              return '-_' . $prefix . substr($field, 2);
 165          } else if (substr($field, 0, 1) === '-') {
 166              return '-' . $prefix . substr($field, 1);
 167          } else if (substr($field, 0, 1) === '_') {
 168              return '_' . $prefix . substr($field, 1);
 169          } else {
 170              return $prefix . $field;
 171          }
 172      }
 173  }