MDL-26442 restore - missing new in qtype match exception
[moodle.git] / question / type / match / backup / moodle2 / restore_qtype_match_plugin.class.php
CommitLineData
41941110
EL
1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * @package moodlecore
20 * @subpackage backup-moodle2
21 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27/**
28 * restore plugin class that provides the necessary information
29 * needed to restore one match qtype plugin
30 */
31class restore_qtype_match_plugin extends restore_qtype_plugin {
32
33 /**
34 * Returns the paths to be handled by the plugin at question level
35 */
36 protected function define_question_plugin_structure() {
37
38 $paths = array();
39
40 // Add own qtype stuff
41 $elename = 'matchoptions';
42 $elepath = $this->get_pathfor('/matchoptions'); // we used get_recommended_name() so this works
43 $paths[] = new restore_path_element($elename, $elepath);
44
45 $elename = 'match';
46 $elepath = $this->get_pathfor('/matches/match'); // we used get_recommended_name() so this works
47 $paths[] = new restore_path_element($elename, $elepath);
48
49
50 return $paths; // And we return the interesting paths
51 }
52
53 /**
54 * Process the qtype/matchoptions element
55 */
56 public function process_matchoptions($data) {
57 global $DB;
58
59 $data = (object)$data;
60 $oldid = $data->id;
61
62 // Detect if the question is created or mapped
63 $oldquestionid = $this->get_old_parentid('question');
64 $newquestionid = $this->get_new_parentid('question');
65 $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false;
66
67 // If the question has been created by restore, we need to create its question_match too
68 if ($questioncreated) {
69 // Adjust some columns
70 $data->question = $newquestionid;
71 // Keep question_match->subquestions unmodified
72 // after_execute_question() will perform the remapping once all subquestions
73 // have been created
74 // Insert record
75 $newitemid = $DB->insert_record('question_match', $data);
76 // Create mapping
77 $this->set_mapping('question_match', $oldid, $newitemid);
78 } else {
79 // Nothing to remap if the question already existed
80 }
81 }
82
83 /**
84 * Process the qtype/matches/match element
85 */
86 public function process_match($data) {
87 global $DB;
88
89 $data = (object)$data;
90 $oldid = $data->id;
91
92 // Detect if the question is created or mapped
93 $oldquestionid = $this->get_old_parentid('question');
94 $newquestionid = $this->get_new_parentid('question');
95 $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false;
96
97 // If the question has been created by restore, we need to create its question_match_sub too
98 if ($questioncreated) {
99 // Adjust some columns
100 $data->question = $newquestionid;
101 // Insert record
102 $newitemid = $DB->insert_record('question_match_sub', $data);
103 // Create mapping (there are files and states based on this)
104 $this->set_mapping('question_match_sub', $oldid, $newitemid);
105
106 // match questions require mapping of question_match_sub, because
107 // they are used by question_states->answer
108 } else {
109 // Look for matching subquestion (by question, questiontext and answertext)
110 $sub = $DB->get_record_select('question_match_sub',
111 'question = ? AND '.$DB->sql_compare_text('questiontext').' = '.$DB->sql_compare_text('?').' AND answertext = ?',
112 array($newquestionid, $data->questiontext, $data->answertext), 'id', IGNORE_MULTIPLE);
113 // Found, let's create the mapping
114 if ($sub) {
115 $this->set_mapping('question_match_sub', $oldid, $sub->id);
116 // Something went really wrong, cannot map subquestion for one match question
117 } else {
303c04f7 118 throw new restore_step_exception('error_question_match_sub_missing_in_db', $data);
41941110
EL
119 }
120 }
121 }
122
123 /**
124 * This method is executed once the whole restore_structure_step,
125 * more exactly ({@link restore_create_categories_and_questions})
126 * has ended processing the whole xml structure. Its name is:
127 * "after_execute_" + connectionpoint ("question")
128 *
129 * For match qtype we use it to restore the subquestions column,
130 * containing one list of question_match_sub ids
131 */
132 public function after_execute_question() {
133 global $DB;
134 // Now that all the question_match_subs have been restored, let's process
135 // the created question_match subquestions (list of question_match_sub ids)
136 $rs = $DB->get_recordset_sql("SELECT qm.id, qm.subquestions
137 FROM {question_match} qm
138 JOIN {backup_ids_temp} bi ON bi.newitemid = qm.question
139 WHERE bi.backupid = ?
140 AND bi.itemname = 'question_created'", array($this->get_restoreid()));
141 foreach ($rs as $rec) {
142 $subquestionsarr = explode(',', $rec->subquestions);
143 foreach ($subquestionsarr as $key => $subquestion) {
144 $subquestionsarr[$key] = $this->get_mappingid('question_match_sub', $subquestion);
145 }
146 $subquestions = implode(',', $subquestionsarr);
147 $DB->set_field('question_match', 'subquestions', $subquestions, array('id' => $rec->id));
148 }
149 $rs->close();
150 }
151
152 /**
153 * Given one question_states record, return the answer
154 * recoded pointing to all the restored stuff for match questions
155 *
156 * answer is one comma separated list of hypen separated pairs
157 * containing question_match_sub->id and question_match_sub->code
158 */
159 public function recode_state_answer($state) {
160 $answer = $state->answer;
161 $resultarr = array();
162 foreach (explode(',', $answer) as $pair) {
163 $pairarr = explode('-', $pair);
164 $id = $pairarr[0];
165 $code = $pairarr[1];
166 $newid = $this->get_mappingid('question_match_sub', $id);
167 $resultarr[] = implode('-', array($newid, $code));
168 }
169 return implode(',', $resultarr);
170 }
9f68f2d5
EL
171
172 /**
173 * Return the contents of this qtype to be processed by the links decoder
174 */
175 static public function define_decode_contents() {
176
177 $contents = array();
178
179 $contents[] = new restore_decode_content('question_match_sub', array('questiontext'), 'question_match_sub');
180
181 return $contents;
182 }
41941110 183}