Commit | Line | Data |
---|---|---|
41941110 | 1 | <?php |
41941110 EL |
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 | ||
a17b297d | 24 | |
41941110 EL |
25 | defined('MOODLE_INTERNAL') || die(); |
26 | ||
a17b297d | 27 | |
41941110 EL |
28 | /** |
29 | * restore plugin class that provides the necessary information | |
30 | * needed to restore one multianswer qtype plugin | |
f7970e3c TH |
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 | |
41941110 EL |
34 | */ |
35 | class restore_qtype_multianswer_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() { | |
41941110 EL |
41 | $paths = array(); |
42 | ||
43 | // This qtype uses question_answers, add them | |
44 | $this->add_question_question_answers($paths); | |
45 | ||
46 | // Add own qtype stuff | |
47 | $elename = 'multianswer'; | |
59a3fcd3 | 48 | $elepath = $this->get_pathfor('/multianswer'); |
41941110 EL |
49 | $paths[] = new restore_path_element($elename, $elepath); |
50 | ||
41941110 EL |
51 | return $paths; // And we return the interesting paths |
52 | } | |
53 | ||
54 | /** | |
55 | * Process the qtype/multianswer element | |
56 | */ | |
57 | public function process_multianswer($data) { | |
58 | global $DB; | |
59 | ||
60 | $data = (object)$data; | |
61 | $oldid = $data->id; | |
62 | ||
63 | // Detect if the question is created or mapped | |
64 | $oldquestionid = $this->get_old_parentid('question'); | |
65 | $newquestionid = $this->get_new_parentid('question'); | |
66 | $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; | |
67 | ||
59a3fcd3 TH |
68 | // If the question has been created by restore, we need to create its |
69 | // question_multianswer too | |
41941110 EL |
70 | if ($questioncreated) { |
71 | // Adjust some columns | |
72 | $data->question = $newquestionid; | |
73 | // Note: multianswer->sequence is a list of question->id values. We aren't | |
74 | // recoding them here (because some questions can be missing yet). Instead | |
75 | // we'll perform the recode in the {@link after_execute} method of the plugin | |
76 | // that gets executed once all questions have been created | |
77 | // Insert record | |
78 | $newitemid = $DB->insert_record('question_multianswer', $data); | |
79 | // Create mapping (need it for after_execute recode of sequence) | |
80 | $this->set_mapping('question_multianswer', $oldid, $newitemid); | |
41941110 EL |
81 | } |
82 | } | |
83 | ||
84 | /** | |
85 | * This method is executed once the whole restore_structure_step | |
86 | * this step is part of ({@link restore_create_categories_and_questions}) | |
87 | * has ended processing the whole xml structure. Its name is: | |
88 | * "after_execute_" + connectionpoint ("question") | |
89 | * | |
90 | * For multianswer qtype we use it to restore the sequence column, | |
91 | * containing one list of question ids | |
92 | */ | |
93 | public function after_execute_question() { | |
94 | global $DB; | |
95 | // Now that all the questions have been restored, let's process | |
96 | // the created question_multianswer sequences (list of question ids) | |
59a3fcd3 TH |
97 | $rs = $DB->get_recordset_sql(" |
98 | SELECT qma.id, qma.sequence | |
99 | FROM {question_multianswer} qma | |
100 | JOIN {backup_ids_temp} bi ON bi.newitemid = qma.question | |
101 | WHERE bi.backupid = ? | |
102 | AND bi.itemname = 'question_created'", | |
103 | array($this->get_restoreid())); | |
41941110 EL |
104 | foreach ($rs as $rec) { |
105 | $sequencearr = explode(',', $rec->sequence); | |
106 | foreach ($sequencearr as $key => $question) { | |
107 | $sequencearr[$key] = $this->get_mappingid('question', $question); | |
108 | } | |
109 | $sequence = implode(',', $sequencearr); | |
59a3fcd3 TH |
110 | $DB->set_field('question_multianswer', 'sequence', $sequence, |
111 | array('id' => $rec->id)); | |
41941110 EL |
112 | } |
113 | $rs->close(); | |
114 | } | |
115 | ||
98a3898e TH |
116 | public function recode_response($questionid, $sequencenumber, array $response) { |
117 | global $DB; | |
118 | ||
119 | $qtypes = $DB->get_records_menu('question', array('parent' => $questionid), | |
120 | '', 'id, qtype'); | |
121 | ||
122 | $sequence = $DB->get_field('question_multianswer', 'sequence', | |
123 | array('question' => $questionid)); | |
124 | ||
125 | $fakestep = new question_attempt_step_read_only($response); | |
126 | ||
127 | foreach (explode(',', $sequence) as $key => $subqid) { | |
128 | $i = $key + 1; | |
129 | ||
130 | $substep = new question_attempt_step_subquestion_adapter($fakestep, 'sub' . $i . '_'); | |
131 | $recodedresponse = $this->step->questions_recode_response_data($qtypes[$subqid], | |
132 | $subqid, $sequencenumber, $substep->get_all_data()); | |
133 | ||
134 | foreach ($recodedresponse as $name => $value) { | |
135 | $response[$substep->add_prefix($name)] = $value; | |
136 | } | |
137 | } | |
138 | ||
139 | return $response; | |
140 | } | |
141 | ||
41941110 EL |
142 | /** |
143 | * Given one question_states record, return the answer | |
144 | * recoded pointing to all the restored stuff for multianswer questions | |
145 | * | |
146 | * answer is one comma separated list of hypen separated pairs | |
147 | * containing sequence (pointing to questions sequence in question_multianswer) | |
148 | * and mixed answers. We'll delegate | |
149 | * the recoding of answers to the proper qtype | |
150 | */ | |
18ab06ba | 151 | public function recode_legacy_state_answer($state) { |
41941110 EL |
152 | global $DB; |
153 | $answer = $state->answer; | |
154 | $resultarr = array(); | |
155 | // Get sequence of questions | |
59a3fcd3 TH |
156 | $sequence = $DB->get_field('question_multianswer', 'sequence', |
157 | array('question' => $state->question)); | |
41941110 EL |
158 | $sequencearr = explode(',', $sequence); |
159 | // Let's process each pair | |
160 | foreach (explode(',', $answer) as $pair) { | |
161 | $pairarr = explode('-', $pair); | |
162 | $sequenceid = $pairarr[0]; | |
163 | $subanswer = $pairarr[1]; | |
164 | // Calculate the questionid based on sequenceid | |
165 | // Note it is already one *new* questionid that doesn't need mapping | |
166 | $questionid = $sequencearr[$sequenceid-1]; | |
167 | // Fetch qtype of the question (needed for delegation) | |
168 | $questionqtype = $DB->get_field('question', 'qtype', array('id' => $questionid)); | |
169 | // Delegate subanswer recode to proper qtype, faking one question_states record | |
170 | $substate = new stdClass(); | |
171 | $substate->question = $questionid; | |
172 | $substate->answer = $subanswer; | |
18ab06ba | 173 | $newanswer = $this->step->restore_recode_legacy_answer($substate, $questionqtype); |
41941110 EL |
174 | $resultarr[] = implode('-', array($sequenceid, $newanswer)); |
175 | } | |
176 | return implode(',', $resultarr); | |
177 | } | |
178 | ||
179 | } |