See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 namespace core_backup; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 global $CFG; 22 require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php"); 23 require_once($CFG->libdir . "/badgeslib.php"); 24 require_once($CFG->dirroot . '/mod/assign/tests/base_test.php'); 25 26 /** 27 * Restore date tests. 28 * 29 * @package core_backup 30 * @copyright 2017 Adrian Greeve <adrian@moodle.com> 31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 */ 33 class restore_stepslib_date_test extends \restore_date_testcase { 34 35 /** 36 * Restoring a manual grade item does not result in the timecreated or 37 * timemodified dates being changed. 38 */ 39 public function test_grade_item_date_restore() { 40 41 $course = $this->getDataGenerator()->create_course(['startdate' => time()]); 42 43 $params = new \stdClass(); 44 $params->courseid = $course->id; 45 $params->fullname = 'unittestgradecalccategory'; 46 $params->aggregation = GRADE_AGGREGATE_MEAN; 47 $params->aggregateonlygraded = 0; 48 $gradecategory = new \grade_category($params, false); 49 $gradecategory->insert(); 50 51 $gradecategory->load_grade_item(); 52 53 $gradeitems = new \grade_item(); 54 $gradeitems->courseid = $course->id; 55 $gradeitems->categoryid = $gradecategory->id; 56 $gradeitems->itemname = 'manual grade_item'; 57 $gradeitems->itemtype = 'manual'; 58 $gradeitems->itemnumber = 0; 59 $gradeitems->needsupdate = false; 60 $gradeitems->gradetype = GRADE_TYPE_VALUE; 61 $gradeitems->grademin = 0; 62 $gradeitems->grademax = 10; 63 $gradeitems->iteminfo = 'Manual grade item used for unit testing'; 64 $gradeitems->timecreated = time(); 65 $gradeitems->timemodified = time(); 66 67 $gradeitems->aggregationcoef = GRADE_AGGREGATE_SUM; 68 69 $gradeitems->insert(); 70 71 $gradeitemparams = [ 72 'itemtype' => 'manual', 73 'itemname' => $gradeitems->itemname, 74 'courseid' => $course->id, 75 ]; 76 77 $gradeitem = \grade_item::fetch($gradeitemparams); 78 79 // Do backup and restore. 80 81 $newcourseid = $this->backup_and_restore($course); 82 $newcourse = get_course($newcourseid); 83 $newgradeitemparams = [ 84 'itemtype' => 'manual', 85 'itemname' => $gradeitems->itemname, 86 'courseid' => $course->id, 87 ]; 88 89 $newgradeitem = \grade_item::fetch($newgradeitemparams); 90 $this->assertEquals($gradeitem->timecreated, $newgradeitem->timecreated); 91 $this->assertEquals($gradeitem->timemodified, $newgradeitem->timemodified); 92 } 93 94 /** 95 * The course section timemodified date does not get rolled forward 96 * when the course is restored. 97 */ 98 public function test_course_section_date_restore() { 99 global $DB; 100 // Create a course. 101 $course = $this->getDataGenerator()->create_course(['startdate' => time()]); 102 // Get the second course section. 103 $section = $DB->get_record('course_sections', ['course' => $course->id, 'section' => '1']); 104 // Do a backup and restore. 105 $newcourseid = $this->backup_and_restore($course); 106 $newcourse = get_course($newcourseid); 107 108 $newsection = $DB->get_record('course_sections', ['course' => $newcourse->id, 'section' => '1']); 109 // Compare dates. 110 $this->assertEquals($section->timemodified, $newsection->timemodified); 111 } 112 113 /** 114 * Test that the timecreated and timemodified dates are not rolled forward when restoring 115 * badge data. 116 */ 117 public function test_badge_date_restore() { 118 global $DB, $USER; 119 // Create a course. 120 $course = $this->getDataGenerator()->create_course(['startdate' => time()]); 121 // Create a badge. 122 $fordb = new \stdClass(); 123 $fordb->id = null; 124 $fordb->name = "Test badge"; 125 $fordb->description = "Testing badges"; 126 $fordb->timecreated = time(); 127 $fordb->timemodified = time(); 128 $fordb->usercreated = $USER->id; 129 $fordb->usermodified = $USER->id; 130 $fordb->issuername = "Test issuer"; 131 $fordb->issuerurl = "http://issuer-url.domain.co.nz"; 132 $fordb->issuercontact = "issuer@example.com"; 133 $fordb->expiredate = time(); 134 $fordb->expireperiod = null; 135 $fordb->type = BADGE_TYPE_COURSE; 136 $fordb->courseid = $course->id; 137 $fordb->messagesubject = "Test message subject"; 138 $fordb->message = "Test message body"; 139 $fordb->attachment = 1; 140 $fordb->notification = 0; 141 $fordb->status = BADGE_STATUS_INACTIVE; 142 $fordb->nextcron = time(); 143 144 $this->badgeid = $DB->insert_record('badge', $fordb, true); 145 // Do a backup and restore. 146 $newcourseid = $this->backup_and_restore($course); 147 $newcourse = get_course($newcourseid); 148 149 $badges = badges_get_badges(BADGE_TYPE_COURSE, $newcourseid); 150 151 // Compare dates. 152 $badge = array_shift($badges); 153 $this->assertEquals($fordb->timecreated, $badge->timecreated); 154 $this->assertEquals($fordb->timemodified, $badge->timemodified); 155 $this->assertEquals($fordb->nextcron, $badge->nextcron); 156 // Expire date should be moved forward. 157 $this->assertNotEquals($fordb->expiredate, $badge->expiredate); 158 } 159 160 /** 161 * Test that course calendar events timemodified field is not rolled forward 162 * when restoring the course. 163 */ 164 public function test_calendarevents_date_restore() { 165 global $USER, $DB; 166 // Create course. 167 $course = $this->getDataGenerator()->create_course(['startdate' => time()]); 168 // Create calendar event. 169 $starttime = time(); 170 $event = [ 171 'name' => 'Start of assignment', 172 'description' => '', 173 'format' => 1, 174 'courseid' => $course->id, 175 'groupid' => 0, 176 'userid' => $USER->id, 177 'modulename' => 0, 178 'instance' => 0, 179 'eventtype' => 'course', 180 'timestart' => $starttime, 181 'timeduration' => 86400, 182 'visible' => 1 183 ]; 184 $calendarevent = \calendar_event::create($event, false); 185 186 // Backup and restore. 187 $newcourseid = $this->backup_and_restore($course); 188 $newcourse = get_course($newcourseid); 189 190 $newevent = $DB->get_record('event', ['courseid' => $newcourseid, 'eventtype' => 'course']); 191 // Compare dates. 192 $this->assertEquals($calendarevent->timemodified, $newevent->timemodified); 193 $this->assertNotEquals($calendarevent->timestart, $newevent->timestart); 194 } 195 196 /** 197 * Testing that the timeenrolled, timestarted, and timecompleted fields are not rolled forward / back 198 * when doing a course restore. 199 */ 200 public function test_course_completion_date_restore() { 201 global $DB; 202 203 // Create course with course completion enabled. 204 $course = $this->getDataGenerator()->create_course(['startdate' => time(), 'enablecompletion' => 1]); 205 206 // Enrol a user in the course. 207 $user = $this->getDataGenerator()->create_user(); 208 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 209 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 210 // Complete the course with a user. 211 $ccompletion = new \completion_completion(['course' => $course->id, 212 'userid' => $user->id, 213 'timeenrolled' => time(), 214 'timestarted' => time() 215 ]); 216 // Now, mark the course as completed. 217 $ccompletion->mark_complete(); 218 $this->assertEquals('100', \core_completion\progress::get_course_progress_percentage($course, $user->id)); 219 220 // Back up and restore. 221 $newcourseid = $this->backup_and_restore($course); 222 $newcourse = get_course($newcourseid); 223 224 $newcompletion = \completion_completion::fetch(['course' => $newcourseid, 'userid' => $user->id]); 225 226 // Compare dates. 227 $this->assertEquals($ccompletion->timeenrolled, $newcompletion->timeenrolled); 228 $this->assertEquals($ccompletion->timestarted, $newcompletion->timestarted); 229 $this->assertEquals($ccompletion->timecompleted, $newcompletion->timecompleted); 230 } 231 232 /** 233 * Testing that the grade grade date information is not changed in the gradebook when a course 234 * restore is performed. 235 */ 236 public function test_grade_grade_date_restore() { 237 global $USER, $DB; 238 // Testing the restore of an overridden grade. 239 list($course, $assign) = $this->create_course_and_module('assign', []); 240 $cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $assign->id]); 241 $assignobj = new \mod_assign_testable_assign(\context_module::instance($cm->id), $cm, $course); 242 $submission = $assignobj->get_user_submission($USER->id, true); 243 $grade = $assignobj->get_user_grade($USER->id, true); 244 $grade->grade = 75; 245 $assignobj->update_grade($grade); 246 247 // Find the grade item. 248 $gradeitemparams = [ 249 'itemtype' => 'mod', 250 'iteminstance' => $assign->id, 251 'itemmodule' => 'assign', 252 'courseid' => $course->id, 253 ]; 254 $gradeitem = \grade_item::fetch($gradeitemparams); 255 256 // Next the grade grade. 257 $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->id, 'userid' => $USER->id]); 258 $gradegrade->set_overridden(true); 259 260 // Back up and restore. 261 $newcourseid = $this->backup_and_restore($course); 262 $newcourse = get_course($newcourseid); 263 264 // Find assignment. 265 $assignid = $DB->get_field('assign', 'id', ['course' => $newcourseid]); 266 // Find grade item. 267 $newgradeitemparams = [ 268 'itemtype' => 'mod', 269 'iteminstance' => $assignid, 270 'itemmodule' => 'assign', 271 'courseid' => $newcourse->id, 272 ]; 273 274 $newgradeitem = \grade_item::fetch($newgradeitemparams); 275 // Find grade grade. 276 $newgradegrade = \grade_grade::fetch(['itemid' => $newgradeitem->id, 'userid' => $USER->id]); 277 // Compare dates. 278 $this->assertEquals($gradegrade->timecreated, $newgradegrade->timecreated); 279 $this->assertEquals($gradegrade->timemodified, $newgradegrade->timemodified); 280 $this->assertEquals($gradegrade->overridden, $newgradegrade->overridden); 281 } 282 283 /** 284 * Checking that the user completion of an activity relating to the timemodified field does not change 285 * when doing a course restore. 286 */ 287 public function test_usercompletion_date_restore() { 288 global $USER, $DB; 289 // More completion... 290 $course = $this->getDataGenerator()->create_course(['startdate' => time(), 'enablecompletion' => 1]); 291 $assign = $this->getDataGenerator()->create_module('assign', [ 292 'course' => $course->id, 293 'completion' => COMPLETION_TRACKING_AUTOMATIC, // Show activity as complete when conditions are met. 294 'completionusegrade' => 1 // Student must receive a grade to complete this activity. 295 ]); 296 $cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $assign->id]); 297 $assignobj = new \mod_assign_testable_assign(\context_module::instance($cm->id), $cm, $course); 298 $submission = $assignobj->get_user_submission($USER->id, true); 299 $grade = $assignobj->get_user_grade($USER->id, true); 300 $grade->grade = 75; 301 $assignobj->update_grade($grade); 302 303 $coursemodulecompletion = $DB->get_record('course_modules_completion', ['coursemoduleid' => $cm->id]); 304 305 // Back up and restore. 306 $newcourseid = $this->backup_and_restore($course); 307 $newcourse = get_course($newcourseid); 308 309 // Find assignment. 310 $assignid = $DB->get_field('assign', 'id', ['course' => $newcourseid]); 311 $cm = $DB->get_record('course_modules', ['course' => $newcourse->id, 'instance' => $assignid]); 312 $newcoursemodulecompletion = $DB->get_record('course_modules_completion', ['coursemoduleid' => $cm->id]); 313 314 $this->assertEquals($coursemodulecompletion->timemodified, $newcoursemodulecompletion->timemodified); 315 } 316 317 /** 318 * Checking that the user completion of an activity relating to the view field does not change 319 * when doing a course restore. 320 * @covers ::backup_and_restore 321 */ 322 public function test_usercompletion_view_restore() { 323 global $DB; 324 // More completion... 325 $course = $this->getDataGenerator()->create_course(['startdate' => time(), 'enablecompletion' => 1]); 326 $student = $this->getDataGenerator()->create_user(); 327 $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student'); 328 $assign = $this->getDataGenerator()->create_module('assign', [ 329 'course' => $course->id, 330 'completion' => COMPLETION_TRACKING_AUTOMATIC, // Show activity as complete when conditions are met. 331 'completionview' => 1 332 ]); 333 $cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $assign->id]); 334 335 // Mark the activity as completed. 336 $completion = new \completion_info($course); 337 $completion->set_module_viewed($cm, $student->id); 338 339 $coursemodulecompletion = $DB->get_record('course_modules_viewed', ['coursemoduleid' => $cm->id]); 340 341 // Back up and restore. 342 $newcourseid = $this->backup_and_restore($course); 343 $newcourse = get_course($newcourseid); 344 345 $assignid = $DB->get_field('assign', 'id', ['course' => $newcourseid]); 346 $cm = $DB->get_record('course_modules', ['course' => $newcourse->id, 'instance' => $assignid]); 347 $newcoursemodulecompletion = $DB->get_record('course_modules_viewed', ['coursemoduleid' => $cm->id]); 348 349 $this->assertEquals($coursemodulecompletion->timecreated, $newcoursemodulecompletion->timecreated); 350 } 351 352 /** 353 * Ensuring that the timemodified field of the question attempt steps table does not change when 354 * a course restore is done. 355 */ 356 public function test_question_attempt_steps_date_restore() { 357 global $DB; 358 359 $course = $this->getDataGenerator()->create_course(['startdate' => time()]); 360 // Make a quiz. 361 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 362 363 $quiz = $quizgenerator->create_instance(array('course' => $course->id, 'questionsperpage' => 0, 'grade' => 100.0, 364 'sumgrades' => 2)); 365 366 $cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $quiz->id]); 367 368 // Create a couple of questions. 369 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 370 371 $cat = $questiongenerator->create_question_category(); 372 $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id)); 373 $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id)); 374 375 // Add them to the quiz. 376 quiz_add_quiz_question($saq->id, $quiz); 377 quiz_add_quiz_question($numq->id, $quiz); 378 379 // Make a user to do the quiz. 380 $user1 = $this->getDataGenerator()->create_user(); 381 382 $quizobj = \quiz::create($quiz->id, $user1->id); 383 384 // Start the attempt. 385 $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); 386 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); 387 388 $timenow = time(); 389 $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user1->id); 390 391 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); 392 393 quiz_attempt_save_started($quizobj, $quba, $attempt); 394 395 // Process some responses from the student. 396 $attemptobj = \quiz_attempt::create($attempt->id); 397 398 $prefix1 = $quba->get_field_prefix(1); 399 $prefix2 = $quba->get_field_prefix(2); 400 401 $tosubmit = array(1 => array('answer' => 'frog'), 402 2 => array('answer' => '3.14')); 403 404 $attemptobj->process_submitted_actions($timenow, false, $tosubmit); 405 406 // Finish the attempt. 407 $attemptobj = \quiz_attempt::create($attempt->id); 408 $attemptobj->process_finish($timenow, false); 409 410 $questionattemptstepdates = []; 411 $originaliterator = $quba->get_attempt_iterator(); 412 foreach ($originaliterator as $questionattempt) { 413 $questionattemptstepdates[] = ['originaldate' => $questionattempt->get_last_action_time()]; 414 } 415 416 // Back up and restore. 417 $newcourseid = $this->backup_and_restore($course); 418 $newcourse = get_course($newcourseid); 419 420 // Get the quiz for this new restored course. 421 $quizdata = $DB->get_record('quiz', ['course' => $newcourseid]); 422 $quizobj = \quiz::create($quizdata->id, $user1->id); 423 424 $questionusage = $DB->get_record('question_usages', [ 425 'component' => 'mod_quiz', 426 'contextid' => $quizobj->get_context()->id 427 ]); 428 429 $newquba = \question_engine::load_questions_usage_by_activity($questionusage->id); 430 431 $restorediterator = $newquba->get_attempt_iterator(); 432 $i = 0; 433 foreach ($restorediterator as $restoredquestionattempt) { 434 $questionattemptstepdates[$i]['restoredate'] = $restoredquestionattempt->get_last_action_time(); 435 $i++; 436 } 437 438 foreach ($questionattemptstepdates as $dates) { 439 $this->assertEquals($dates['originaldate'], $dates['restoredate']); 440 } 441 } 442 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body