Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.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   * @package    moodlecore
  19   * @subpackage backup-moodle2
  20   * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  21   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  
  28  /**
  29   * restore plugin class that provides the necessary information
  30   * needed to restore one multichoice qtype plugin
  31   *
  32   * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  33   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  class restore_qtype_multichoice_plugin extends restore_qtype_plugin {
  36  
  37      /**
  38       * Returns the paths to be handled by the plugin at question level
  39       */
  40      protected function define_question_plugin_structure() {
  41  
  42          $paths = array();
  43  
  44          // This qtype uses question_answers, add them.
  45          $this->add_question_question_answers($paths);
  46  
  47          // Add own qtype stuff.
  48          $elename = 'multichoice';
  49          // We used get_recommended_name() so this works.
  50          $elepath = $this->get_pathfor('/multichoice');
  51          $paths[] = new restore_path_element($elename, $elepath);
  52  
  53          return $paths; // And we return the interesting paths.
  54      }
  55  
  56      /**
  57       * Process the qtype/multichoice element
  58       */
  59      public function process_multichoice($data) {
  60          global $DB;
  61  
  62          $data = (object)$data;
  63          $oldid = $data->id;
  64  
  65          // Detect if the question is created or mapped.
  66          $oldquestionid   = $this->get_old_parentid('question');
  67          $newquestionid   = $this->get_new_parentid('question');
  68          $questioncreated = (bool) $this->get_mappingid('question_created', $oldquestionid);
  69  
  70          // If the question has been created by restore, we need to create its
  71          // qtype_multichoice_options too.
  72          if ($questioncreated) {
  73              $data->questionid = $newquestionid;
  74  
  75              // It is possible for old backup files to contain unique key violations.
  76              // We need to check to avoid that.
  77              if (!$DB->record_exists('qtype_multichoice_options', array('questionid' => $data->questionid))) {
  78                  $newitemid = $DB->insert_record('qtype_multichoice_options', $data);
  79                  $this->set_mapping('qtype_multichoice_options', $oldid, $newitemid);
  80              }
  81          }
  82      }
  83  
  84      public function recode_response($questionid, $sequencenumber, array $response) {
  85          if (array_key_exists('_order', $response)) {
  86              $response['_order'] = $this->recode_choice_order($response['_order']);
  87          }
  88          return $response;
  89      }
  90  
  91      /**
  92       * Recode the choice order as stored in the response.
  93       * @param string $order the original order.
  94       * @return string the recoded order.
  95       */
  96      protected function recode_choice_order($order) {
  97          $neworder = array();
  98          foreach (explode(',', $order) as $id) {
  99              if ($newid = $this->get_mappingid('question_answer', $id)) {
 100                  $neworder[] = $newid;
 101              }
 102          }
 103          return implode(',', $neworder);
 104      }
 105  
 106      /**
 107       * Given one question_states record, return the answer
 108       * recoded pointing to all the restored stuff for multichoice questions
 109       *
 110       * answer are two (hypen speparated) lists of comma separated question_answers
 111       * the first to specify the order of the answers and the second to specify the
 112       * responses. Note the order list (the first one) can be optional
 113       */
 114      public function recode_legacy_state_answer($state) {
 115          $answer = $state->answer;
 116          $orderarr = array();
 117          $responsesarr = array();
 118          $lists = explode(':', $answer);
 119          // If only 1 list, answer is missing the order list, adjust.
 120          if (count($lists) == 1) {
 121              $lists[1] = $lists[0]; // Here we have the responses.
 122              $lists[0] = '';        // Here we have the order.
 123          }
 124          // Map order.
 125          if (!empty($lists[0])) {
 126              foreach (explode(',', $lists[0]) as $id) {
 127                  if ($newid = $this->get_mappingid('question_answer', $id)) {
 128                      $orderarr[] = $newid;
 129                  }
 130              }
 131          }
 132          // Map responses.
 133          if (!empty($lists[1])) {
 134              foreach (explode(',', $lists[1]) as $id) {
 135                  if ($newid = $this->get_mappingid('question_answer', $id)) {
 136                      $responsesarr[] = $newid;
 137                  }
 138              }
 139          }
 140          // Build the final answer, if not order, only responses.
 141          $result = '';
 142          if (empty($orderarr)) {
 143              $result = implode(',', $responsesarr);
 144          } else {
 145              $result = implode(',', $orderarr) . ':' . implode(',', $responsesarr);
 146          }
 147          return $result;
 148      }
 149  
 150      /**
 151       * Return the contents of this qtype to be processed by the links decoder
 152       */
 153      public static function define_decode_contents() {
 154  
 155          $contents = array();
 156  
 157          $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
 158          $contents[] = new restore_decode_content('qtype_multichoice_options',
 159                  $fields, 'qtype_multichoice_options');
 160  
 161          return $contents;
 162      }
 163  }