[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 mod_quiz 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 * Structure step to restore one quiz activity 30 * 31 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class restore_quiz_activity_structure_step extends restore_questions_activity_structure_step { 35 36 /** 37 * @var bool tracks whether the quiz contains at least one section. Before 38 * Moodle 2.9 quiz sections did not exist, so if the file being restored 39 * did not contain any, we need to create one in {@link after_execute()}. 40 */ 41 protected $sectioncreated = false; 42 43 /** 44 * @var bool when restoring old quizzes (2.8 or before) this records the 45 * shufflequestionsoption quiz option which has moved to the quiz_sections table. 46 */ 47 protected $legacyshufflequestionsoption = false; 48 49 protected function define_structure() { 50 51 $paths = array(); 52 $userinfo = $this->get_setting_value('userinfo'); 53 54 $quiz = new restore_path_element('quiz', '/activity/quiz'); 55 $paths[] = $quiz; 56 57 // A chance for access subplugings to set up their quiz data. 58 $this->add_subplugin_structure('quizaccess', $quiz); 59 60 $paths[] = new restore_path_element('quiz_question_instance', 61 '/activity/quiz/question_instances/question_instance'); 62 $paths[] = new restore_path_element('quiz_section', '/activity/quiz/sections/section'); 63 $paths[] = new restore_path_element('quiz_feedback', '/activity/quiz/feedbacks/feedback'); 64 $paths[] = new restore_path_element('quiz_override', '/activity/quiz/overrides/override'); 65 66 if ($userinfo) { 67 $paths[] = new restore_path_element('quiz_grade', '/activity/quiz/grades/grade'); 68 69 if ($this->task->get_old_moduleversion() > 2011010100) { 70 // Restoring from a version 2.1 dev or later. 71 // Process the new-style attempt data. 72 $quizattempt = new restore_path_element('quiz_attempt', 73 '/activity/quiz/attempts/attempt'); 74 $paths[] = $quizattempt; 75 76 // Add states and sessions. 77 $this->add_question_usages($quizattempt, $paths); 78 79 // A chance for access subplugings to set up their attempt data. 80 $this->add_subplugin_structure('quizaccess', $quizattempt); 81 82 } else { 83 // Restoring from a version 2.0.x+ or earlier. 84 // Upgrade the legacy attempt data. 85 $quizattempt = new restore_path_element('quiz_attempt_legacy', 86 '/activity/quiz/attempts/attempt', 87 true); 88 $paths[] = $quizattempt; 89 $this->add_legacy_question_attempt_data($quizattempt, $paths); 90 } 91 } 92 93 // Return the paths wrapped into standard activity structure. 94 return $this->prepare_activity_structure($paths); 95 } 96 97 protected function process_quiz($data) { 98 global $CFG, $DB; 99 100 $data = (object)$data; 101 $oldid = $data->id; 102 $data->course = $this->get_courseid(); 103 104 $data->timeopen = $this->apply_date_offset($data->timeopen); 105 $data->timeclose = $this->apply_date_offset($data->timeclose); 106 $data->timecreated = $this->apply_date_offset($data->timecreated); 107 $data->timemodified = $this->apply_date_offset($data->timemodified); 108 109 if (property_exists($data, 'questions')) { 110 // Needed by {@link process_quiz_attempt_legacy}, in which case it will be present. 111 $this->oldquizlayout = $data->questions; 112 } 113 114 // The setting quiz->attempts can come both in data->attempts and 115 // data->attempts_number, handle both. MDL-26229. 116 if (isset($data->attempts_number)) { 117 $data->attempts = $data->attempts_number; 118 unset($data->attempts_number); 119 } 120 121 // The old optionflags and penaltyscheme from 2.0 need to be mapped to 122 // the new preferredbehaviour. See MDL-20636. 123 if (!isset($data->preferredbehaviour)) { 124 if (empty($data->optionflags)) { 125 $data->preferredbehaviour = 'deferredfeedback'; 126 } else if (empty($data->penaltyscheme)) { 127 $data->preferredbehaviour = 'adaptivenopenalty'; 128 } else { 129 $data->preferredbehaviour = 'adaptive'; 130 } 131 unset($data->optionflags); 132 unset($data->penaltyscheme); 133 } 134 135 // The old review column from 2.0 need to be split into the seven new 136 // review columns. See MDL-20636. 137 if (isset($data->review)) { 138 require_once($CFG->dirroot . '/mod/quiz/locallib.php'); 139 140 if (!defined('QUIZ_OLD_IMMEDIATELY')) { 141 define('QUIZ_OLD_IMMEDIATELY', 0x3c003f); 142 define('QUIZ_OLD_OPEN', 0x3c00fc0); 143 define('QUIZ_OLD_CLOSED', 0x3c03f000); 144 145 define('QUIZ_OLD_RESPONSES', 1*0x1041); 146 define('QUIZ_OLD_SCORES', 2*0x1041); 147 define('QUIZ_OLD_FEEDBACK', 4*0x1041); 148 define('QUIZ_OLD_ANSWERS', 8*0x1041); 149 define('QUIZ_OLD_SOLUTIONS', 16*0x1041); 150 define('QUIZ_OLD_GENERALFEEDBACK', 32*0x1041); 151 define('QUIZ_OLD_OVERALLFEEDBACK', 1*0x4440000); 152 } 153 154 $oldreview = $data->review; 155 156 $data->reviewattempt = 157 mod_quiz_display_options::DURING | 158 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_RESPONSES ? 159 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 160 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_RESPONSES ? 161 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 162 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_RESPONSES ? 163 mod_quiz_display_options::AFTER_CLOSE : 0); 164 165 $data->reviewcorrectness = 166 mod_quiz_display_options::DURING | 167 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ? 168 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 169 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_SCORES ? 170 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 171 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ? 172 mod_quiz_display_options::AFTER_CLOSE : 0); 173 174 $data->reviewmarks = 175 mod_quiz_display_options::DURING | 176 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ? 177 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 178 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_SCORES ? 179 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 180 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ? 181 mod_quiz_display_options::AFTER_CLOSE : 0); 182 183 $data->reviewspecificfeedback = 184 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK ? 185 mod_quiz_display_options::DURING : 0) | 186 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK ? 187 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 188 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_FEEDBACK ? 189 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 190 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_FEEDBACK ? 191 mod_quiz_display_options::AFTER_CLOSE : 0); 192 193 $data->reviewgeneralfeedback = 194 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK ? 195 mod_quiz_display_options::DURING : 0) | 196 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK ? 197 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 198 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_GENERALFEEDBACK ? 199 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 200 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_GENERALFEEDBACK ? 201 mod_quiz_display_options::AFTER_CLOSE : 0); 202 203 $data->reviewrightanswer = 204 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS ? 205 mod_quiz_display_options::DURING : 0) | 206 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS ? 207 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 208 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_ANSWERS ? 209 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 210 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_ANSWERS ? 211 mod_quiz_display_options::AFTER_CLOSE : 0); 212 213 $data->reviewoverallfeedback = 214 0 | 215 ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_OVERALLFEEDBACK ? 216 mod_quiz_display_options::IMMEDIATELY_AFTER : 0) | 217 ($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_OVERALLFEEDBACK ? 218 mod_quiz_display_options::LATER_WHILE_OPEN : 0) | 219 ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_OVERALLFEEDBACK ? 220 mod_quiz_display_options::AFTER_CLOSE : 0); 221 } 222 223 // The old popup column from from <= 2.1 need to be mapped to 224 // the new browsersecurity. See MDL-29627. 225 if (!isset($data->browsersecurity)) { 226 if (empty($data->popup)) { 227 $data->browsersecurity = '-'; 228 } else if ($data->popup == 1) { 229 $data->browsersecurity = 'securewindow'; 230 } else if ($data->popup == 2) { 231 $data->browsersecurity = 'safebrowser'; 232 } else { 233 $data->preferredbehaviour = '-'; 234 } 235 unset($data->popup); 236 } 237 238 if (!isset($data->overduehandling)) { 239 $data->overduehandling = get_config('quiz', 'overduehandling'); 240 } 241 242 // Insert the quiz record. 243 $newitemid = $DB->insert_record('quiz', $data); 244 // Immediately after inserting "activity" record, call this. 245 $this->apply_activity_instance($newitemid); 246 } 247 248 protected function process_quiz_question_instance($data) { 249 global $DB; 250 251 $data = (object)$data; 252 253 // Backwards compatibility for old field names (MDL-43670). 254 if (!isset($data->questionid) && isset($data->question)) { 255 $data->questionid = $data->question; 256 } 257 if (!isset($data->maxmark) && isset($data->grade)) { 258 $data->maxmark = $data->grade; 259 } 260 261 if (!property_exists($data, 'slot')) { 262 $page = 1; 263 $slot = 1; 264 foreach (explode(',', $this->oldquizlayout) as $item) { 265 if ($item == 0) { 266 $page += 1; 267 continue; 268 } 269 if ($item == $data->questionid) { 270 $data->slot = $slot; 271 $data->page = $page; 272 break; 273 } 274 $slot += 1; 275 } 276 } 277 278 if (!property_exists($data, 'slot')) { 279 // There was a question_instance in the backup file for a question 280 // that was not acutally in the quiz. Drop it. 281 $this->log('question ' . $data->questionid . ' was associated with quiz ' . 282 $this->get_new_parentid('quiz') . ' but not actually used. ' . 283 'The instance has been ignored.', backup::LOG_INFO); 284 return; 285 } 286 287 $data->quizid = $this->get_new_parentid('quiz'); 288 $data->questionid = $this->get_mappingid('question', $data->questionid); 289 290 $DB->insert_record('quiz_slots', $data); 291 } 292 293 protected function process_quiz_section($data) { 294 global $DB; 295 296 $data = (object) $data; 297 $data->quizid = $this->get_new_parentid('quiz'); 298 $newitemid = $DB->insert_record('quiz_sections', $data); 299 $this->sectioncreated = true; 300 } 301 302 protected function process_quiz_feedback($data) { 303 global $DB; 304 305 $data = (object)$data; 306 $oldid = $data->id; 307 308 $data->quizid = $this->get_new_parentid('quiz'); 309 310 $newitemid = $DB->insert_record('quiz_feedback', $data); 311 $this->set_mapping('quiz_feedback', $oldid, $newitemid, true); // Has related files. 312 } 313 314 protected function process_quiz_override($data) { 315 global $DB; 316 317 $data = (object)$data; 318 $oldid = $data->id; 319 320 // Based on userinfo, we'll restore user overides or no. 321 $userinfo = $this->get_setting_value('userinfo'); 322 323 // Skip user overrides if we are not restoring userinfo. 324 if (!$userinfo && !is_null($data->userid)) { 325 return; 326 } 327 328 $data->quiz = $this->get_new_parentid('quiz'); 329 330 if ($data->userid !== null) { 331 $data->userid = $this->get_mappingid('user', $data->userid); 332 } 333 334 if ($data->groupid !== null) { 335 $data->groupid = $this->get_mappingid('group', $data->groupid); 336 } 337 338 $data->timeopen = $this->apply_date_offset($data->timeopen); 339 $data->timeclose = $this->apply_date_offset($data->timeclose); 340 341 $newitemid = $DB->insert_record('quiz_overrides', $data); 342 343 // Add mapping, restore of logs needs it. 344 $this->set_mapping('quiz_override', $oldid, $newitemid); 345 } 346 347 protected function process_quiz_grade($data) { 348 global $DB; 349 350 $data = (object)$data; 351 $oldid = $data->id; 352 353 $data->quiz = $this->get_new_parentid('quiz'); 354 355 $data->userid = $this->get_mappingid('user', $data->userid); 356 $data->grade = $data->gradeval; 357 358 $data->timemodified = $this->apply_date_offset($data->timemodified); 359 360 $DB->insert_record('quiz_grades', $data); 361 } 362 363 protected function process_quiz_attempt($data) { 364 $data = (object)$data; 365 366 $data->quiz = $this->get_new_parentid('quiz'); 367 $data->attempt = $data->attemptnum; 368 369 $data->userid = $this->get_mappingid('user', $data->userid); 370 371 $data->timestart = $this->apply_date_offset($data->timestart); 372 $data->timefinish = $this->apply_date_offset($data->timefinish); 373 $data->timemodified = $this->apply_date_offset($data->timemodified); 374 if (!empty($data->timecheckstate)) { 375 $data->timecheckstate = $this->apply_date_offset($data->timecheckstate); 376 } else { 377 $data->timecheckstate = 0; 378 } 379 380 // Deals with up-grading pre-2.3 back-ups to 2.3+. 381 if (!isset($data->state)) { 382 if ($data->timefinish > 0) { 383 $data->state = 'finished'; 384 } else { 385 $data->state = 'inprogress'; 386 } 387 } 388 389 // The data is actually inserted into the database later in inform_new_usage_id. 390 $this->currentquizattempt = clone($data); 391 } 392 393 protected function process_quiz_attempt_legacy($data) { 394 global $DB; 395 396 $this->process_quiz_attempt($data); 397 398 $quiz = $DB->get_record('quiz', array('id' => $this->get_new_parentid('quiz'))); 399 $quiz->oldquestions = $this->oldquizlayout; 400 $this->process_legacy_quiz_attempt_data($data, $quiz); 401 } 402 403 protected function inform_new_usage_id($newusageid) { 404 global $DB; 405 406 $data = $this->currentquizattempt; 407 408 $oldid = $data->id; 409 $data->uniqueid = $newusageid; 410 411 $newitemid = $DB->insert_record('quiz_attempts', $data); 412 413 // Save quiz_attempt->id mapping, because logs use it. 414 $this->set_mapping('quiz_attempt', $oldid, $newitemid, false); 415 } 416 417 protected function after_execute() { 418 global $DB; 419 420 parent::after_execute(); 421 // Add quiz related files, no need to match by itemname (just internally handled context). 422 $this->add_related_files('mod_quiz', 'intro', null); 423 // Add feedback related files, matching by itemname = 'quiz_feedback'. 424 $this->add_related_files('mod_quiz', 'feedback', 'quiz_feedback'); 425 426 if (!$this->sectioncreated) { 427 $DB->insert_record('quiz_sections', array( 428 'quizid' => $this->get_new_parentid('quiz'), 429 'firstslot' => 1, 'heading' => '', 430 'shufflequestions' => $this->legacyshufflequestionsoption)); 431 } 432 } 433 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |