[ Index ] |
PHP Cross Reference of moodle-2.8 |
[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 * Upgrade script for the quiz module. 19 * 20 * @package mod_quiz 21 * @copyright 2006 Eloy Lafuente (stronk7) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 29 /** 30 * Quiz module upgrade function. 31 * @param string $oldversion the version we are upgrading from. 32 */ 33 function xmldb_quiz_upgrade($oldversion) { 34 global $CFG, $DB; 35 36 $dbman = $DB->get_manager(); 37 38 // Moodle v2.2.0 release upgrade line. 39 // Put any upgrade step following this. 40 41 if ($oldversion < 2011120700) { 42 43 // Define field lastcron to be dropped from quiz_reports. 44 $table = new xmldb_table('quiz_reports'); 45 $field = new xmldb_field('lastcron'); 46 47 // Conditionally launch drop field lastcron. 48 if ($dbman->field_exists($table, $field)) { 49 $dbman->drop_field($table, $field); 50 } 51 52 // Quiz savepoint reached. 53 upgrade_mod_savepoint(true, 2011120700, 'quiz'); 54 } 55 56 if ($oldversion < 2011120701) { 57 58 // Define field cron to be dropped from quiz_reports. 59 $table = new xmldb_table('quiz_reports'); 60 $field = new xmldb_field('cron'); 61 62 // Conditionally launch drop field cron. 63 if ($dbman->field_exists($table, $field)) { 64 $dbman->drop_field($table, $field); 65 } 66 67 // Quiz savepoint reached. 68 upgrade_mod_savepoint(true, 2011120701, 'quiz'); 69 } 70 71 if ($oldversion < 2011120703) { 72 // Track page of quiz attempts. 73 $table = new xmldb_table('quiz_attempts'); 74 75 $field = new xmldb_field('currentpage', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0); 76 77 if (!$dbman->field_exists($table, $field)) { 78 $dbman->add_field($table, $field); 79 } 80 upgrade_mod_savepoint(true, 2011120703, 'quiz'); 81 } 82 83 if ($oldversion < 2012030901) { 84 // Configuration option for navigation method. 85 $table = new xmldb_table('quiz'); 86 87 $field = new xmldb_field('navmethod', XMLDB_TYPE_CHAR, '16', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 'free'); 88 89 if (!$dbman->field_exists($table, $field)) { 90 $dbman->add_field($table, $field); 91 } 92 upgrade_mod_savepoint(true, 2012030901, 'quiz'); 93 } 94 95 if ($oldversion < 2012040198) { 96 // This step was added later. In MDL-32727, it was found that adding the 97 // unique index on quiz-userid-attempt sometimes failed because of 98 // duplicate entries {quizid}-{userid}-{attempt}. We do two things to 99 // prevent these problems. First, here, we delete all preview attempts. 100 101 // This code is an approximate copy-and-paste from 102 // question_engine_data_mapper::delete_questions_usage_by_activities 103 // Note that, for simplicity, the MySQL performance hack has been removed. 104 // Since this code is for upgrade only, performance in not so critical, 105 // where as simplicity of testing the code is. 106 107 // Note that there is a limit to how far I am prepared to go in eliminating 108 // all calls to library functions in this upgrade code. The only library 109 // function still being used in question_engine::get_all_response_file_areas(); 110 // I think it is pretty safe not to inline it here. 111 112 // Get a list of response variables that have files. 113 require_once($CFG->dirroot . '/question/type/questiontypebase.php'); 114 $variables = array(); 115 foreach (core_component::get_plugin_list('qtype') as $qtypename => $path) { 116 $file = $path . '/questiontype.php'; 117 if (!is_readable($file)) { 118 continue; 119 } 120 include_once($file); 121 $class = 'qtype_' . $qtypename; 122 if (!class_exists($class)) { 123 continue; 124 } 125 $qtype = new $class(); 126 if (!method_exists($qtype, 'response_file_areas')) { 127 continue; 128 } 129 $variables += $qtype->response_file_areas(); 130 } 131 132 // Conver that to a list of actual file area names. 133 $fileareas = array(); 134 foreach (array_unique($variables) as $variable) { 135 $fileareas[] = 'response_' . $variable; 136 } 137 // No point checking if this is empty as an optimisation, because essay 138 // has response file areas, so the array will never be empty. 139 140 // Get all the contexts where there are previews. 141 $contextids = $DB->get_records_sql_menu(" 142 SELECT DISTINCT qu.contextid, 1 143 FROM {question_usages} qu 144 JOIN {quiz_attempts} quiza ON quiza.uniqueid = qu.id 145 WHERE quiza.preview = 1"); 146 147 // Loop over contexts and files areas, deleting all files. 148 $fs = get_file_storage(); 149 foreach ($contextids as $contextid => $notused) { 150 foreach ($fileareas as $filearea) { 151 upgrade_set_timeout(300); 152 $fs->delete_area_files_select($contextid, 'question', $filearea, 153 "IN (SELECT qas.id 154 FROM {question_attempt_steps} qas 155 JOIN {question_attempts} qa ON qa.id = qas.questionattemptid 156 JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid 157 WHERE quiza.preview = 1)"); 158 } 159 } 160 161 // Now delete the question data associated with the previews. 162 $DB->delete_records_select('question_attempt_step_data', "attemptstepid IN ( 163 SELECT qas.id 164 FROM {question_attempt_steps} qas 165 JOIN {question_attempts} qa ON qa.id = qas.questionattemptid 166 JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid 167 WHERE quiza.preview = 1)"); 168 169 $DB->delete_records_select('question_attempt_steps', "questionattemptid IN ( 170 SELECT qa.id 171 FROM {question_attempts} qa 172 JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid 173 WHERE quiza.preview = 1)"); 174 175 $DB->delete_records_select('question_attempts', "{question_attempts}.questionusageid IN ( 176 SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)"); 177 178 $DB->delete_records_select('question_usages', "{question_usages}.id IN ( 179 SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)"); 180 181 // Finally delete the previews. 182 $DB->delete_records('quiz_attempts', array('preview' => 1)); 183 184 // Quiz savepoint reached. 185 upgrade_mod_savepoint(true, 2012040198, 'quiz'); 186 } 187 188 if ($oldversion < 2012040199) { 189 // This step was added later. In MDL-32727, it was found that adding the 190 // unique index on quiz-userid-attempt sometimes failed because of 191 // duplicate entries {quizid}-{userid}-{attempt}. 192 // Here, if there are still duplicate entires, we renumber the values in 193 // the attempt column. 194 195 // Load all the problem quiz attempts. 196 $problems = $DB->get_recordset_sql(' 197 SELECT qa.id, qa.quiz, qa.userid, qa.attempt 198 FROM {quiz_attempts} qa 199 JOIN ( 200 SELECT DISTINCT quiz, userid 201 FROM {quiz_attempts} 202 GROUP BY quiz, userid, attempt 203 HAVING COUNT(1) > 1 204 ) problems_view ON problems_view.quiz = qa.quiz AND 205 problems_view.userid = qa.userid 206 ORDER BY qa.quiz, qa.userid, qa.attempt, qa.id'); 207 208 // Renumber them. 209 $currentquiz = null; 210 $currentuserid = null; 211 $attempt = 1; 212 foreach ($problems as $problem) { 213 if ($problem->quiz !== $currentquiz || $problem->userid !== $currentuserid) { 214 $currentquiz = $problem->quiz; 215 $currentuserid = $problem->userid; 216 $attempt = 1; 217 } 218 if ($attempt != $problem->attempt) { 219 $DB->set_field('quiz_attempts', 'attempt', $attempt, array('id' => $problem->id)); 220 } 221 $attempt += 1; 222 } 223 224 $problems->close(); 225 226 // Quiz savepoint reached. 227 upgrade_mod_savepoint(true, 2012040199, 'quiz'); 228 } 229 230 if ($oldversion < 2012040200) { 231 // Define index userid to be dropped form quiz_attempts 232 $table = new xmldb_table('quiz_attempts'); 233 $index = new xmldb_index('userid', XMLDB_INDEX_NOTUNIQUE, array('userid')); 234 235 // Conditionally launch drop index quiz-userid-attempt. 236 if ($dbman->index_exists($table, $index)) { 237 $dbman->drop_index($table, $index); 238 } 239 240 // Quiz savepoint reached. 241 upgrade_mod_savepoint(true, 2012040200, 'quiz'); 242 } 243 244 if ($oldversion < 2012040201) { 245 246 // Define key userid (foreign) to be added to quiz_attempts. 247 $table = new xmldb_table('quiz_attempts'); 248 $key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id')); 249 250 // Launch add key userid. 251 $dbman->add_key($table, $key); 252 253 // Quiz savepoint reached. 254 upgrade_mod_savepoint(true, 2012040201, 'quiz'); 255 } 256 257 if ($oldversion < 2012040202) { 258 259 // Define index quiz-userid-attempt (unique) to be added to quiz_attempts. 260 $table = new xmldb_table('quiz_attempts'); 261 $index = new xmldb_index('quiz-userid-attempt', XMLDB_INDEX_UNIQUE, array('quiz', 'userid', 'attempt')); 262 263 // Conditionally launch add index quiz-userid-attempt. 264 if (!$dbman->index_exists($table, $index)) { 265 $dbman->add_index($table, $index); 266 } 267 268 // Quiz savepoint reached. 269 upgrade_mod_savepoint(true, 2012040202, 'quiz'); 270 } 271 272 if ($oldversion < 2012040203) { 273 274 // Define field state to be added to quiz_attempts. 275 $table = new xmldb_table('quiz_attempts'); 276 $field = new xmldb_field('state', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'inprogress', 'preview'); 277 278 // Conditionally launch add field state. 279 if (!$dbman->field_exists($table, $field)) { 280 $dbman->add_field($table, $field); 281 } 282 283 // Quiz savepoint reached. 284 upgrade_mod_savepoint(true, 2012040203, 'quiz'); 285 } 286 287 if ($oldversion < 2012040204) { 288 289 // Update quiz_attempts.state for finished attempts. 290 $DB->set_field_select('quiz_attempts', 'state', 'finished', 'timefinish > 0'); 291 292 // Other, more complex transitions (basically abandoned attempts), will 293 // be handled by cron later. 294 295 // Quiz savepoint reached. 296 upgrade_mod_savepoint(true, 2012040204, 'quiz'); 297 } 298 299 if ($oldversion < 2012040205) { 300 301 // Define field overduehandling to be added to quiz. 302 $table = new xmldb_table('quiz'); 303 $field = new xmldb_field('overduehandling', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'autoabandon', 'timelimit'); 304 305 // Conditionally launch add field overduehandling. 306 if (!$dbman->field_exists($table, $field)) { 307 $dbman->add_field($table, $field); 308 } 309 310 // Quiz savepoint reached. 311 upgrade_mod_savepoint(true, 2012040205, 'quiz'); 312 } 313 314 if ($oldversion < 2012040206) { 315 316 // Define field graceperiod to be added to quiz. 317 $table = new xmldb_table('quiz'); 318 $field = new xmldb_field('graceperiod', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'overduehandling'); 319 320 // Conditionally launch add field graceperiod. 321 if (!$dbman->field_exists($table, $field)) { 322 $dbman->add_field($table, $field); 323 } 324 325 // Quiz savepoint reached. 326 upgrade_mod_savepoint(true, 2012040206, 'quiz'); 327 } 328 329 // Moodle v2.3.0 release upgrade line 330 // Put any upgrade step following this 331 332 if ($oldversion < 2012061702) { 333 334 // MDL-32791 somebody reported having nonsense rows in their 335 // quiz_question_instances which caused various problems. These rows 336 // are meaningless, hence this upgrade step to clean them up. 337 $DB->delete_records('quiz_question_instances', array('question' => 0)); 338 339 // Quiz savepoint reached. 340 upgrade_mod_savepoint(true, 2012061702, 'quiz'); 341 } 342 343 if ($oldversion < 2012061703) { 344 345 // MDL-34702 the questiondecimalpoints column was created with default -2 346 // when it should have been -1, and no-one has noticed in the last 2+ years! 347 348 // Changing the default of field questiondecimalpoints on table quiz to -1. 349 $table = new xmldb_table('quiz'); 350 $field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '-1', 'decimalpoints'); 351 352 // Launch change of default for field questiondecimalpoints. 353 $dbman->change_field_default($table, $field); 354 355 // Correct any wrong values. 356 $DB->set_field('quiz', 'questiondecimalpoints', -1, array('questiondecimalpoints' => -2)); 357 358 // Quiz savepoint reached. 359 upgrade_mod_savepoint(true, 2012061703, 'quiz'); 360 } 361 362 if ($oldversion < 2012100801) { 363 364 // Define field timecheckstate to be added to quiz_attempts 365 $table = new xmldb_table('quiz_attempts'); 366 $field = new xmldb_field('timecheckstate', XMLDB_TYPE_INTEGER, '10', null, null, null, '0', 'timemodified'); 367 368 // Conditionally launch add field timecheckstate 369 if (!$dbman->field_exists($table, $field)) { 370 $dbman->add_field($table, $field); 371 } 372 373 // Define index state-timecheckstate (not unique) to be added to quiz_attempts 374 $table = new xmldb_table('quiz_attempts'); 375 $index = new xmldb_index('state-timecheckstate', XMLDB_INDEX_NOTUNIQUE, array('state', 'timecheckstate')); 376 377 // Conditionally launch add index state-timecheckstate 378 if (!$dbman->index_exists($table, $index)) { 379 $dbman->add_index($table, $index); 380 } 381 382 // Overdue cron no longer needs these 383 unset_config('overduelastrun', 'quiz'); 384 unset_config('overduedoneto', 'quiz'); 385 386 // Update timecheckstate on all open attempts 387 require_once($CFG->dirroot . '/mod/quiz/locallib.php'); 388 quiz_update_open_attempts(array()); 389 390 // quiz savepoint reached 391 upgrade_mod_savepoint(true, 2012100801, 'quiz'); 392 } 393 394 // Moodle v2.4.0 release upgrade line 395 // Put any upgrade step following this 396 397 if ($oldversion < 2013031900) { 398 // Quiz manual grading UI should be controlled by mod/quiz:grade, not :viewreports. 399 $DB->set_field('quiz_reports', 'capability', 'mod/quiz:grade', array('name' => 'grading')); 400 401 // Mod quiz savepoint reached. 402 upgrade_mod_savepoint(true, 2013031900, 'quiz'); 403 } 404 405 // Moodle v2.5.0 release upgrade line. 406 // Put any upgrade step following this. 407 408 409 // Moodle v2.6.0 release upgrade line. 410 // Put any upgrade step following this. 411 412 if ($oldversion < 2014011300) { 413 414 // Define key quiz (foreign) to be dropped form quiz_question_instances. 415 $table = new xmldb_table('quiz_question_instances'); 416 $key = new xmldb_key('quiz', XMLDB_KEY_FOREIGN, array('quiz'), 'quiz', array('id')); 417 418 // Launch drop key quiz. 419 $dbman->drop_key($table, $key); 420 421 // Quiz savepoint reached. 422 upgrade_mod_savepoint(true, 2014011300, 'quiz'); 423 } 424 425 if ($oldversion < 2014011301) { 426 427 // Rename field quiz on table quiz_question_instances to quizid. 428 $table = new xmldb_table('quiz_question_instances'); 429 $field = new xmldb_field('quiz', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id'); 430 431 // Launch rename field quiz. 432 $dbman->rename_field($table, $field, 'quizid'); 433 434 // Quiz savepoint reached. 435 upgrade_mod_savepoint(true, 2014011301, 'quiz'); 436 } 437 438 if ($oldversion < 2014011302) { 439 440 // Define key quizid (foreign) to be added to quiz_question_instances. 441 $table = new xmldb_table('quiz_question_instances'); 442 $key = new xmldb_key('quizid', XMLDB_KEY_FOREIGN, array('quizid'), 'quiz', array('id')); 443 444 // Launch add key quizid. 445 $dbman->add_key($table, $key); 446 447 // Quiz savepoint reached. 448 upgrade_mod_savepoint(true, 2014011302, 'quiz'); 449 } 450 451 if ($oldversion < 2014011303) { 452 453 // Define key question (foreign) to be dropped form quiz_question_instances. 454 $table = new xmldb_table('quiz_question_instances'); 455 $key = new xmldb_key('question', XMLDB_KEY_FOREIGN, array('question'), 'question', array('id')); 456 457 // Launch drop key question. 458 $dbman->drop_key($table, $key); 459 460 // Quiz savepoint reached. 461 upgrade_mod_savepoint(true, 2014011303, 'quiz'); 462 } 463 464 if ($oldversion < 2014011304) { 465 466 // Rename field question on table quiz_question_instances to questionid. 467 $table = new xmldb_table('quiz_question_instances'); 468 $field = new xmldb_field('question', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'quiz'); 469 470 // Launch rename field question. 471 $dbman->rename_field($table, $field, 'questionid'); 472 473 // Quiz savepoint reached. 474 upgrade_mod_savepoint(true, 2014011304, 'quiz'); 475 } 476 477 if ($oldversion < 2014011305) { 478 479 // Define key questionid (foreign) to be added to quiz_question_instances. 480 $table = new xmldb_table('quiz_question_instances'); 481 $key = new xmldb_key('questionid', XMLDB_KEY_FOREIGN, array('questionid'), 'question', array('id')); 482 483 // Launch add key questionid. 484 $dbman->add_key($table, $key); 485 486 // Quiz savepoint reached. 487 upgrade_mod_savepoint(true, 2014011305, 'quiz'); 488 } 489 490 if ($oldversion < 2014011306) { 491 492 // Rename field grade on table quiz_question_instances to maxmark. 493 $table = new xmldb_table('quiz_question_instances'); 494 $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'question'); 495 496 // Launch rename field grade. 497 $dbman->rename_field($table, $field, 'maxmark'); 498 499 // Quiz savepoint reached. 500 upgrade_mod_savepoint(true, 2014011306, 'quiz'); 501 } 502 503 if ($oldversion < 2014021300) { 504 505 // Define field needsupgradetonewqe to be dropped from quiz_attempts. 506 $table = new xmldb_table('quiz_attempts'); 507 $field = new xmldb_field('needsupgradetonewqe'); 508 509 // Conditionally launch drop field needsupgradetonewqe. 510 if ($dbman->field_exists($table, $field)) { 511 $dbman->drop_field($table, $field); 512 } 513 514 // Quiz savepoint reached. 515 upgrade_mod_savepoint(true, 2014021300, 'quiz'); 516 } 517 518 if ($oldversion < 2014022000) { 519 520 // Define table quiz_question_instances to be renamed to quiz_slots. 521 $table = new xmldb_table('quiz_question_instances'); 522 523 // Launch rename table for quiz_question_instances. 524 $dbman->rename_table($table, 'quiz_slots'); 525 526 // Quiz savepoint reached. 527 upgrade_mod_savepoint(true, 2014022000, 'quiz'); 528 } 529 530 if ($oldversion < 2014022001) { 531 532 // Define field slot to be added to quiz_slots. 533 $table = new xmldb_table('quiz_slots'); 534 $field = new xmldb_field('slot', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'id'); 535 536 // Conditionally launch add field slot. 537 if (!$dbman->field_exists($table, $field)) { 538 $dbman->add_field($table, $field); 539 } 540 541 // Quiz savepoint reached. 542 upgrade_mod_savepoint(true, 2014022001, 'quiz'); 543 } 544 545 if ($oldversion < 2014022002) { 546 547 // Define field page to be added to quiz_slots. 548 $table = new xmldb_table('quiz_slots'); 549 $field = new xmldb_field('page', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'quizid'); 550 551 // Conditionally launch add field page. 552 if (!$dbman->field_exists($table, $field)) { 553 $dbman->add_field($table, $field); 554 } 555 556 // Quiz savepoint reached. 557 upgrade_mod_savepoint(true, 2014022002, 'quiz'); 558 } 559 560 if ($oldversion < 2014022003) { 561 562 // Use the information in the old quiz.questions column to fill in the 563 // new slot and page columns. 564 $numquizzes = $DB->count_records('quiz'); 565 if ($numquizzes > 0) { 566 $pbar = new progress_bar('quizquestionstoslots', 500, true); 567 $transaction = $DB->start_delegated_transaction(); 568 569 $numberdone = 0; 570 $quizzes = $DB->get_recordset('quiz', null, 'id', 'id,questions,sumgrades'); 571 foreach ($quizzes as $quiz) { 572 if ($quiz->questions === '') { 573 $questionsinorder = array(); 574 } else { 575 $questionsinorder = explode(',', $quiz->questions); 576 } 577 578 $questionidtoslotrowid = $DB->get_records_menu('quiz_slots', 579 array('quizid' => $quiz->id), '', 'id, questionid'); 580 581 $problemfound = false; 582 $currentpage = 1; 583 $slot = 1; 584 foreach ($questionsinorder as $questionid) { 585 if ($questionid === '0') { 586 // Page break. 587 $currentpage++; 588 continue; 589 } 590 591 if ($questionid === '') { 592 // This can happen as the result of old restore bugs. 593 // There can be a missing number in the list of ids. 594 // All we can do about this is ignore it, which is what 595 // the quiz system used to do. See MDL-45321. 596 continue; 597 } 598 599 $key = array_search($questionid, $questionidtoslotrowid); 600 if ($key !== false) { 601 // Normal case. quiz_slots entry is present. 602 // Just need to add slot and page. 603 $quizslot = new stdClass(); 604 $quizslot->id = $key; 605 $quizslot->slot = $slot; 606 $quizslot->page = $currentpage; 607 $DB->update_record('quiz_slots', $quizslot); 608 609 unset($questionidtoslotrowid[$key]); // So we can do a sanity check later. 610 $slot++; 611 continue; 612 613 } else { 614 // This should not happen. The question was listed in 615 // quiz.questions, but there was not an entry for it in 616 // quiz_slots (formerly quiz_question_instances). 617 // Previously, if such question ids were found, then 618 // starting an attempt at the quiz would throw an exception. 619 // Here, we try to add the missing data. 620 $problemfound = true; 621 $defaultmark = $DB->get_field('question', 'defaultmark', 622 array('id' => $questionid), IGNORE_MISSING); 623 if ($defaultmark === false) { 624 debugging('During upgrade, detected that question ' . 625 $questionid . ' was listed as being part of quiz ' . 626 $quiz->id . ' but this question no longer exists. Ignoring it.', DEBUG_NORMAL); 627 628 // Non-existent question. Ignore it completely. 629 continue; 630 } 631 632 debugging('During upgrade, detected that question ' . 633 $questionid . ' was listed as being part of quiz ' . 634 $quiz->id . ' but there was not entry for it in ' . 635 'quiz_question_instances/quiz_slots. Creating an entry with default mark.', DEBUG_NORMAL); 636 $quizslot = new stdClass(); 637 $quizslot->quizid = $quiz->id; 638 $quizslot->slot = $slot; 639 $quizslot->page = $currentpage; 640 $quizslot->questionid = $questionid; 641 $quizslot->maxmark = $defaultmark; 642 $DB->insert_record('quiz_slots', $quizslot); 643 644 $slot++; 645 continue; 646 } 647 648 } 649 650 // Now, as a sanity check, ensure we have done all the 651 // quiz_slots rows linked to this quiz. 652 if (!empty($questionidtoslotrowid)) { 653 debugging('During upgrade, detected that questions ' . 654 implode(', ', array_values($questionidtoslotrowid)) . 655 ' had instances in quiz ' . $quiz->id . ' but were not actually used. ' . 656 'The instances have been removed.', DEBUG_NORMAL); 657 658 $DB->delete_records_list('quiz_slots', 'id', array_keys($questionidtoslotrowid)); 659 $problemfound = true; 660 } 661 662 // If there were problems found, we probably need to re-compute 663 // quiz.sumgrades. 664 if ($problemfound) { 665 // C/f the quiz_update_sumgrades function in locallib.php, 666 // but note that what we do here is a bit simpler. 667 $newsumgrades = $DB->get_field_sql( 668 "SELECT SUM(maxmark) 669 FROM {quiz_slots} 670 WHERE quizid = ?", 671 array($quiz->id)); 672 if (!$newsumgrades) { 673 $newsumgrades = 0; 674 } 675 if (abs($newsumgrades - $quiz->sumgrades) > 0.000005) { 676 debugging('Because of the previously mentioned problems, ' . 677 'sumgrades for quiz ' . $quiz->id . 678 ' was changed from ' . $quiz->sumgrades . ' to ' . 679 $newsumgrades . ' You should probably check that this quiz is still working: ' . 680 $CFG->wwwroot . '/mod/quiz/view.php?q=' . $quiz->id . '.', DEBUG_NORMAL); 681 $DB->set_field('quiz', 'sumgrades', $newsumgrades, array('id' => $quiz->id)); 682 } 683 } 684 685 // Done with this quiz. Update progress bar. 686 $numberdone++; 687 $pbar->update($numberdone, $numquizzes, 688 "Upgrading quiz structure - {$numberdone}/{$numquizzes}."); 689 } 690 691 $transaction->allow_commit(); 692 } 693 694 // Quiz savepoint reached. 695 upgrade_mod_savepoint(true, 2014022003, 'quiz'); 696 } 697 698 if ($oldversion < 2014022004) { 699 700 // If, for any reason, there were any quiz_slots missed, then try 701 // to do something about that now before we add the NOT NULL constraints. 702 // In fact, becuase of the sanity check at the end of the above check, 703 // any such quiz_slots rows must refer to a non-existent quiz id, so 704 // delete them. 705 $DB->delete_records_select('quiz_slots', 706 'NOT EXISTS (SELECT 1 FROM {quiz} q WHERE q.id = quizid)'); 707 708 // Quiz savepoint reached. 709 upgrade_mod_savepoint(true, 2014022004, 'quiz'); 710 711 // Now, if any quiz_slots rows are left with slot or page NULL, something 712 // is badly wrong. 713 if ($DB->record_exists_select('quiz_slots', 'slot IS NULL OR page IS NULL')) { 714 throw new coding_exception('Something went wrong in the quiz upgrade step for MDL-43749. ' . 715 'Some quiz_slots still contain NULLs which will break the NOT NULL constraints we need to add. ' . 716 'Please report this problem at http://tracker.moodle.org/ so that it can be investigated. Thank you.'); 717 } 718 } 719 720 if ($oldversion < 2014022005) { 721 722 // Changing nullability of field slot on table quiz_slots to not null. 723 $table = new xmldb_table('quiz_slots'); 724 $field = new xmldb_field('slot', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id'); 725 726 // Launch change of nullability for field slot. 727 $dbman->change_field_notnull($table, $field); 728 729 // Quiz savepoint reached. 730 upgrade_mod_savepoint(true, 2014022005, 'quiz'); 731 } 732 733 if ($oldversion < 2014022006) { 734 735 // Changing nullability of field page on table quiz_slots to not null. 736 $table = new xmldb_table('quiz_slots'); 737 $field = new xmldb_field('page', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'quizid'); 738 739 // Launch change of nullability for field page. 740 $dbman->change_field_notnull($table, $field); 741 742 // Quiz savepoint reached. 743 upgrade_mod_savepoint(true, 2014022006, 'quiz'); 744 } 745 746 if ($oldversion < 2014022007) { 747 748 // Define index quizid-slot (unique) to be added to quiz_slots. 749 $table = new xmldb_table('quiz_slots'); 750 $index = new xmldb_index('quizid-slot', XMLDB_INDEX_UNIQUE, array('quizid', 'slot')); 751 752 // Conditionally launch add index quizid-slot. 753 if (!$dbman->index_exists($table, $index)) { 754 $dbman->add_index($table, $index); 755 } 756 757 // Quiz savepoint reached. 758 upgrade_mod_savepoint(true, 2014022007, 'quiz'); 759 } 760 761 if ($oldversion < 2014022008) { 762 763 // Define field questions to be dropped from quiz. 764 $table = new xmldb_table('quiz'); 765 $field = new xmldb_field('questions'); 766 767 // Conditionally launch drop field questions. 768 if ($dbman->field_exists($table, $field)) { 769 $dbman->drop_field($table, $field); 770 } 771 772 // Quiz savepoint reached. 773 upgrade_mod_savepoint(true, 2014022008, 'quiz'); 774 } 775 776 // Moodle v2.7.0 release upgrade line. 777 // Put any upgrade step following this. 778 779 if ($oldversion < 2014052800) { 780 781 // Define field completionattemptsexhausted to be added to quiz. 782 $table = new xmldb_table('quiz'); 783 $field = new xmldb_field('completionattemptsexhausted', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'showblocks'); 784 785 // Conditionally launch add field completionattemptsexhausted. 786 if (!$dbman->field_exists($table, $field)) { 787 $dbman->add_field($table, $field); 788 } 789 // Quiz savepoint reached. 790 upgrade_mod_savepoint(true, 2014052800, 'quiz'); 791 } 792 793 if ($oldversion < 2014052801) { 794 // Define field completionpass to be added to quiz. 795 $table = new xmldb_table('quiz'); 796 $field = new xmldb_field('completionpass', XMLDB_TYPE_INTEGER, '1', null, null, null, 0, 'completionattemptsexhausted'); 797 798 // Conditionally launch add field completionpass. 799 if (!$dbman->field_exists($table, $field)) { 800 $dbman->add_field($table, $field); 801 } 802 803 // Quiz savepoint reached. 804 upgrade_mod_savepoint(true, 2014052801, 'quiz'); 805 } 806 807 // Moodle v2.8.0 release upgrade line. 808 // Put any upgrade step following this. 809 810 return true; 811 } 812
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |