Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310]

   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   * Course copy tests.
  19   *
  20   * @package    core_backup
  21   * @copyright  2020 onward The Moodle Users Association <https://moodleassociation.org/>
  22   * @author     Matt Porritt <mattp@catalyst-au.net>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  global $CFG;
  28  require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
  29  require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
  30  require_once($CFG->libdir . '/completionlib.php');
  31  
  32  /**
  33   * Course copy tests.
  34   *
  35   * @package    core_backup
  36   * @copyright  2020 onward The Moodle Users Association <https://moodleassociation.org/>
  37   * @author     Matt Porritt <mattp@catalyst-au.net>
  38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class core_backup_course_copy_testcase extends advanced_testcase {
  41  
  42      /**
  43       *
  44       * @var \stdClass Course used for testing.
  45       */
  46      protected $course;
  47  
  48      /**
  49       *
  50       * @var int User used to perform backups.
  51       */
  52      protected $userid;
  53  
  54      /**
  55       *
  56       * @var array Ids of users in test course.
  57       */
  58      protected $courseusers;
  59  
  60      /**
  61       *
  62       * @var array Names of the created activities.
  63       */
  64      protected $activitynames;
  65  
  66      /**
  67       * Set up tasks for all tests.
  68       */
  69      protected function setUp(): void {
  70          global $DB, $CFG, $USER;
  71  
  72          $this->resetAfterTest(true);
  73  
  74          $CFG->enableavailability = true;
  75          $CFG->enablecompletion = true;
  76  
  77          // Create a course with some availability data set.
  78          $generator = $this->getDataGenerator();
  79          $course = $generator->create_course(
  80              array('format' => 'topics', 'numsections' => 3,
  81                  'enablecompletion' => COMPLETION_ENABLED),
  82              array('createsections' => true));
  83          $forum = $generator->create_module('forum', array(
  84              'course' => $course->id));
  85          $forum2 = $generator->create_module('forum', array(
  86              'course' => $course->id, 'completion' => COMPLETION_TRACKING_MANUAL));
  87  
  88          // We need a grade, easiest is to add an assignment.
  89          $assignrow = $generator->create_module('assign', array(
  90              'course' => $course->id));
  91          $assign = new assign(context_module::instance($assignrow->cmid), false, false);
  92          $item = $assign->get_grade_item();
  93  
  94          // Make a test grouping as well.
  95          $grouping = $generator->create_grouping(array('courseid' => $course->id,
  96              'name' => 'Grouping!'));
  97  
  98          // Create some users.
  99          $user1 = $generator->create_user();
 100          $user2 = $generator->create_user();
 101          $user3 = $generator->create_user();
 102          $user4 = $generator->create_user();
 103          $this->courseusers = array(
 104              $user1->id, $user2->id, $user3->id, $user4->id
 105          );
 106  
 107          // Enrol users into the course.
 108          $generator->enrol_user($user1->id, $course->id, 'student');
 109          $generator->enrol_user($user2->id, $course->id, 'editingteacher');
 110          $generator->enrol_user($user3->id, $course->id, 'manager');
 111          $generator->enrol_user($user4->id, $course->id, 'editingteacher');
 112          $generator->enrol_user($user4->id, $course->id, 'manager');
 113  
 114          $availability = '{"op":"|","show":false,"c":[' .
 115              '{"type":"completion","cm":' . $forum2->cmid .',"e":1},' .
 116              '{"type":"grade","id":' . $item->id . ',"min":4,"max":94},' .
 117              '{"type":"grouping","id":' . $grouping->id . '}' .
 118              ']}';
 119          $DB->set_field('course_modules', 'availability', $availability, array(
 120              'id' => $forum->cmid));
 121          $DB->set_field('course_sections', 'availability', $availability, array(
 122              'course' => $course->id, 'section' => 1));
 123  
 124          // Add some user data to the course.
 125          $discussion = $generator->get_plugin_generator('mod_forum')->create_discussion(['course' => $course->id,
 126              'forum' => $forum->id, 'userid' => $user1->id, 'timemodified' => time(),
 127              'name' => 'Frog']);
 128          $generator->get_plugin_generator('mod_forum')->create_post(['discussion' => $discussion->id, 'userid' => $user1->id]);
 129  
 130          $this->course  = $course;
 131          $this->userid = $USER->id; // Admin.
 132          $this->activitynames = array(
 133              $forum->name,
 134              $forum2->name,
 135              $assignrow->name
 136          );
 137  
 138          // Set the user doing the backup to be a manager in the course.
 139          // By default Managers can restore courses AND users, teachers can only do users.
 140          $this->setUser($user3);
 141  
 142          // Disable all loggers.
 143          $CFG->backup_error_log_logger_level = backup::LOG_NONE;
 144          $CFG->backup_output_indented_logger_level = backup::LOG_NONE;
 145          $CFG->backup_file_logger_level = backup::LOG_NONE;
 146          $CFG->backup_database_logger_level = backup::LOG_NONE;
 147          $CFG->backup_file_logger_level_extra = backup::LOG_NONE;
 148      }
 149  
 150      /**
 151       * Test creating a course copy.
 152       */
 153      public function test_create_copy() {
 154  
 155          // Mock up the form data.
 156          $formdata = new \stdClass;
 157          $formdata->courseid = $this->course->id;
 158          $formdata->fullname = 'foo';
 159          $formdata->shortname = 'bar';
 160          $formdata->category = 1;
 161          $formdata->visible = 1;
 162          $formdata->startdate = 1582376400;
 163          $formdata->enddate = 0;
 164          $formdata->idnumber = 123;
 165          $formdata->userdata = 1;
 166          $formdata->role_1 = 1;
 167          $formdata->role_3 = 3;
 168          $formdata->role_5 = 5;
 169  
 170          $coursecopy = new \core_backup\copy\copy($formdata);
 171          $result = $coursecopy->create_copy();
 172  
 173          // Load the controllers, to extract the data we need.
 174          $bc = \backup_controller::load_controller($result['backupid']);
 175          $rc = \restore_controller::load_controller($result['restoreid']);
 176  
 177          // Check the backup controller.
 178          $this->assertEquals($result, $bc->get_copy()->copyids);
 179          $this->assertEquals(backup::MODE_COPY, $bc->get_mode());
 180          $this->assertEquals($this->course->id, $bc->get_courseid());
 181          $this->assertEquals(backup::TYPE_1COURSE, $bc->get_type());
 182  
 183          // Check the restore controller.
 184          $newcourseid = $rc->get_courseid();
 185          $newcourse = get_course($newcourseid);
 186  
 187          $this->assertEquals($result, $rc->get_copy()->copyids);
 188          $this->assertEquals(get_string('copyingcourse', 'backup'), $newcourse->fullname);
 189          $this->assertEquals(get_string('copyingcourseshortname', 'backup'), $newcourse->shortname);
 190          $this->assertEquals(backup::MODE_COPY, $rc->get_mode());
 191          $this->assertEquals($newcourseid, $rc->get_courseid());
 192  
 193          // Check the created ad-hoc task.
 194          $now = time();
 195          $task = \core\task\manager::get_next_adhoc_task($now);
 196  
 197          $this->assertInstanceOf('\\core\\task\\asynchronous_copy_task', $task);
 198          $this->assertEquals($result, (array)$task->get_custom_data());
 199          $this->assertFalse($task->is_blocking());
 200  
 201          \core\task\manager::adhoc_task_complete($task);
 202      }
 203  
 204      /**
 205       * Test getting the current copies.
 206       */
 207      public function test_get_copies() {
 208          global $USER;
 209  
 210          // Mock up the form data.
 211          $formdata = new \stdClass;
 212          $formdata->courseid = $this->course->id;
 213          $formdata->fullname = 'foo';
 214          $formdata->shortname = 'bar';
 215          $formdata->category = 1;
 216          $formdata->visible = 1;
 217          $formdata->startdate = 1582376400;
 218          $formdata->enddate = 0;
 219          $formdata->idnumber = '';
 220          $formdata->userdata = 1;
 221          $formdata->role_1 = 1;
 222          $formdata->role_3 = 3;
 223          $formdata->role_5 = 5;
 224  
 225          $formdata2 = clone($formdata);
 226          $formdata2->shortname = 'tree';
 227  
 228          // Create some copies.
 229          $coursecopy = new \core_backup\copy\copy($formdata);
 230          $result = $coursecopy->create_copy();
 231  
 232          // Backup, awaiting.
 233          $copies = \core_backup\copy\copy::get_copies($USER->id);
 234          $this->assertEquals($result['backupid'], $copies[0]->backupid);
 235          $this->assertEquals($result['restoreid'], $copies[0]->restoreid);
 236          $this->assertEquals(\backup::STATUS_AWAITING, $copies[0]->status);
 237          $this->assertEquals(\backup::OPERATION_BACKUP, $copies[0]->operation);
 238  
 239          $bc = \backup_controller::load_controller($result['backupid']);
 240  
 241          // Backup, in progress.
 242          $bc->set_status(\backup::STATUS_EXECUTING);
 243          $copies = \core_backup\copy\copy::get_copies($USER->id);
 244          $this->assertEquals($result['backupid'], $copies[0]->backupid);
 245          $this->assertEquals($result['restoreid'], $copies[0]->restoreid);
 246          $this->assertEquals(\backup::STATUS_EXECUTING, $copies[0]->status);
 247          $this->assertEquals(\backup::OPERATION_BACKUP, $copies[0]->operation);
 248  
 249          // Restore, ready to process.
 250          $bc->set_status(\backup::STATUS_FINISHED_OK);
 251          $copies = \core_backup\copy\copy::get_copies($USER->id);
 252          $this->assertEquals($result['backupid'], $copies[0]->backupid);
 253          $this->assertEquals($result['restoreid'], $copies[0]->restoreid);
 254          $this->assertEquals(\backup::STATUS_REQUIRE_CONV, $copies[0]->status);
 255          $this->assertEquals(\backup::OPERATION_RESTORE, $copies[0]->operation);
 256  
 257          // No records.
 258          $bc->set_status(\backup::STATUS_FINISHED_ERR);
 259          $copies = \core_backup\copy\copy::get_copies($USER->id);
 260          $this->assertEmpty($copies);
 261  
 262          $coursecopy2 = new \core_backup\copy\copy($formdata2);
 263          $result2 = $coursecopy2->create_copy();
 264          // Set the second copy to be complete.
 265          $bc = \backup_controller::load_controller($result2['backupid']);
 266          $bc->set_status(\backup::STATUS_FINISHED_OK);
 267          // Set the restore to be finished.
 268          $rc = \backup_controller::load_controller($result2['restoreid']);
 269          $rc->set_status(\backup::STATUS_FINISHED_OK);
 270  
 271          // No records.
 272          $copies = \core_backup\copy\copy::get_copies($USER->id);
 273          $this->assertEmpty($copies);
 274      }
 275  
 276      /**
 277       * Test getting the current copies for specific course.
 278       */
 279      public function test_get_copies_course() {
 280          global $USER;
 281  
 282          // Mock up the form data.
 283          $formdata = new \stdClass;
 284          $formdata->courseid = $this->course->id;
 285          $formdata->fullname = 'foo';
 286          $formdata->shortname = 'bar';
 287          $formdata->category = 1;
 288          $formdata->visible = 1;
 289          $formdata->startdate = 1582376400;
 290          $formdata->enddate = 0;
 291          $formdata->idnumber = '';
 292          $formdata->userdata = 1;
 293          $formdata->role_1 = 1;
 294          $formdata->role_3 = 3;
 295          $formdata->role_5 = 5;
 296  
 297          // Create some copies.
 298          $coursecopy = new \core_backup\copy\copy($formdata);
 299          $coursecopy->create_copy();
 300  
 301          // No copies match this course id.
 302          $copies = \core_backup\copy\copy::get_copies($USER->id, ($this->course->id + 1));
 303          $this->assertEmpty($copies);
 304      }
 305  
 306      /**
 307       * Test getting the current copies if course has been deleted.
 308       */
 309      public function test_get_copies_course_deleted() {
 310          global $USER;
 311  
 312          // Mock up the form data.
 313          $formdata = new \stdClass;
 314          $formdata->courseid = $this->course->id;
 315          $formdata->fullname = 'foo';
 316          $formdata->shortname = 'bar';
 317          $formdata->category = 1;
 318          $formdata->visible = 1;
 319          $formdata->startdate = 1582376400;
 320          $formdata->enddate = 0;
 321          $formdata->idnumber = '';
 322          $formdata->userdata = 1;
 323          $formdata->role_1 = 1;
 324          $formdata->role_3 = 3;
 325          $formdata->role_5 = 5;
 326  
 327          // Create some copies.
 328          $coursecopy = new \core_backup\copy\copy($formdata);
 329          $coursecopy->create_copy();
 330  
 331          delete_course($this->course->id, false);
 332  
 333          // No copies match this course id as it has been deleted.
 334          $copies = \core_backup\copy\copy::get_copies($USER->id, ($this->course->id));
 335          $this->assertEmpty($copies);
 336      }
 337  
 338      /*
 339       * Test course copy.
 340       */
 341      public function test_course_copy() {
 342          global $DB;
 343  
 344          // Mock up the form data.
 345          $formdata = new \stdClass;
 346          $formdata->courseid = $this->course->id;
 347          $formdata->fullname = 'copy course';
 348          $formdata->shortname = 'copy course short';
 349          $formdata->category = 1;
 350          $formdata->visible = 0;
 351          $formdata->startdate = 1582376400;
 352          $formdata->enddate = 1582386400;
 353          $formdata->idnumber = 123;
 354          $formdata->userdata = 1;
 355          $formdata->role_1 = 1;
 356          $formdata->role_3 = 3;
 357          $formdata->role_5 = 5;
 358  
 359          // Create the course copy records and associated ad-hoc task.
 360          $coursecopy = new \core_backup\copy\copy($formdata);
 361          $copyids = $coursecopy->create_copy();
 362  
 363          $courseid = $this->course->id;
 364  
 365          // We are expecting trace output during this test.
 366          $this->expectOutputRegex("/$courseid/");
 367  
 368          // Execute adhoc task.
 369          $now = time();
 370          $task = \core\task\manager::get_next_adhoc_task($now);
 371          $this->assertInstanceOf('\\core\\task\\asynchronous_copy_task', $task);
 372          $task->execute();
 373          \core\task\manager::adhoc_task_complete($task);
 374  
 375          $postbackuprec = $DB->get_record('backup_controllers', array('backupid' => $copyids['backupid']));
 376          $postrestorerec = $DB->get_record('backup_controllers', array('backupid' => $copyids['restoreid']));
 377  
 378          // Check backup was completed successfully.
 379          $this->assertEquals(backup::STATUS_FINISHED_OK, $postbackuprec->status);
 380          $this->assertEquals(1.0, $postbackuprec->progress);
 381  
 382          // Check restore was completed successfully.
 383          $this->assertEquals(backup::STATUS_FINISHED_OK, $postrestorerec->status);
 384          $this->assertEquals(1.0, $postrestorerec->progress);
 385  
 386          // Check the restored course itself.
 387          $coursecontext = context_course::instance($postrestorerec->itemid);
 388          $users = get_enrolled_users($coursecontext);
 389  
 390          $modinfo = get_fast_modinfo($postrestorerec->itemid);
 391          $forums = $modinfo->get_instances_of('forum');
 392          $forum = reset($forums);
 393          $discussions = forum_get_discussions($forum);
 394          $course = $modinfo->get_course();
 395  
 396          $this->assertEquals($formdata->startdate, $course->startdate);
 397          $this->assertEquals($formdata->enddate, $course->enddate);
 398          $this->assertEquals('copy course', $course->fullname);
 399          $this->assertEquals('copy course short',  $course->shortname);
 400          $this->assertEquals(0,  $course->visible);
 401          $this->assertEquals(123,  $course->idnumber);
 402  
 403          foreach ($modinfo->get_cms() as $cm) {
 404              $this->assertContains($cm->get_formatted_name(), $this->activitynames);
 405          }
 406  
 407          foreach ($this->courseusers as $user) {
 408              $this->assertEquals($user, $users[$user]->id);
 409          }
 410  
 411          $this->assertEquals(count($this->courseusers), count($users));
 412          $this->assertEquals(2, count($discussions));
 413      }
 414  
 415      /*
 416       * Test course copy, not including any users (or data).
 417       */
 418      public function test_course_copy_no_users() {
 419          global $DB;
 420  
 421          // Mock up the form data.
 422          $formdata = new \stdClass;
 423          $formdata->courseid = $this->course->id;
 424          $formdata->fullname = 'copy course';
 425          $formdata->shortname = 'copy course short';
 426          $formdata->category = 1;
 427          $formdata->visible = 0;
 428          $formdata->startdate = 1582376400;
 429          $formdata->enddate = 1582386400;
 430          $formdata->idnumber = 123;
 431          $formdata->userdata = 1;
 432          $formdata->role_1 = 0;
 433          $formdata->role_3 = 0;
 434          $formdata->role_5 = 0;
 435  
 436          // Create the course copy records and associated ad-hoc task.
 437          $coursecopy = new \core_backup\copy\copy($formdata);
 438          $copyids = $coursecopy->create_copy();
 439  
 440          $courseid = $this->course->id;
 441  
 442          // We are expecting trace output during this test.
 443          $this->expectOutputRegex("/$courseid/");
 444  
 445          // Execute adhoc task.
 446          $now = time();
 447          $task = \core\task\manager::get_next_adhoc_task($now);
 448          $this->assertInstanceOf('\\core\\task\\asynchronous_copy_task', $task);
 449          $task->execute();
 450          \core\task\manager::adhoc_task_complete($task);
 451  
 452          $postrestorerec = $DB->get_record('backup_controllers', array('backupid' => $copyids['restoreid']));
 453  
 454          // Check the restored course itself.
 455          $coursecontext = context_course::instance($postrestorerec->itemid);
 456          $users = get_enrolled_users($coursecontext);
 457  
 458          $modinfo = get_fast_modinfo($postrestorerec->itemid);
 459          $forums = $modinfo->get_instances_of('forum');
 460          $forum = reset($forums);
 461          $discussions = forum_get_discussions($forum);
 462          $course = $modinfo->get_course();
 463  
 464          $this->assertEquals($formdata->startdate, $course->startdate);
 465          $this->assertEquals($formdata->enddate, $course->enddate);
 466          $this->assertEquals('copy course', $course->fullname);
 467          $this->assertEquals('copy course short',  $course->shortname);
 468          $this->assertEquals(0,  $course->visible);
 469          $this->assertEquals(123,  $course->idnumber);
 470  
 471          foreach ($modinfo->get_cms() as $cm) {
 472              $this->assertContains($cm->get_formatted_name(), $this->activitynames);
 473          }
 474  
 475          // Should be no discussions as the user that made them wasn't included.
 476          $this->assertEquals(0, count($discussions));
 477  
 478          // There should only be one user in the new course, and that's the user who did the copy.
 479          $this->assertEquals(1, count($users));
 480          $this->assertEquals($this->courseusers[2], $users[$this->courseusers[2]]->id);
 481  
 482      }
 483  
 484      /*
 485       * Test course copy, including students and their data.
 486       */
 487      public function test_course_copy_students_data() {
 488          global $DB;
 489  
 490          // Mock up the form data.
 491          $formdata = new \stdClass;
 492          $formdata->courseid = $this->course->id;
 493          $formdata->fullname = 'copy course';
 494          $formdata->shortname = 'copy course short';
 495          $formdata->category = 1;
 496          $formdata->visible = 0;
 497          $formdata->startdate = 1582376400;
 498          $formdata->enddate = 1582386400;
 499          $formdata->idnumber = 123;
 500          $formdata->userdata = 1;
 501          $formdata->role_1 = 0;
 502          $formdata->role_3 = 0;
 503          $formdata->role_5 = 5;
 504  
 505          // Create the course copy records and associated ad-hoc task.
 506          $coursecopy = new \core_backup\copy\copy($formdata);
 507          $copyids = $coursecopy->create_copy();
 508  
 509          $courseid = $this->course->id;
 510  
 511          // We are expecting trace output during this test.
 512          $this->expectOutputRegex("/$courseid/");
 513  
 514          // Execute adhoc task.
 515          $now = time();
 516          $task = \core\task\manager::get_next_adhoc_task($now);
 517          $this->assertInstanceOf('\\core\\task\\asynchronous_copy_task', $task);
 518          $task->execute();
 519          \core\task\manager::adhoc_task_complete($task);
 520  
 521          $postrestorerec = $DB->get_record('backup_controllers', array('backupid' => $copyids['restoreid']));
 522  
 523          // Check the restored course itself.
 524          $coursecontext = context_course::instance($postrestorerec->itemid);
 525          $users = get_enrolled_users($coursecontext);
 526  
 527          $modinfo = get_fast_modinfo($postrestorerec->itemid);
 528          $forums = $modinfo->get_instances_of('forum');
 529          $forum = reset($forums);
 530          $discussions = forum_get_discussions($forum);
 531          $course = $modinfo->get_course();
 532  
 533          $this->assertEquals($formdata->startdate, $course->startdate);
 534          $this->assertEquals($formdata->enddate, $course->enddate);
 535          $this->assertEquals('copy course', $course->fullname);
 536          $this->assertEquals('copy course short',  $course->shortname);
 537          $this->assertEquals(0,  $course->visible);
 538          $this->assertEquals(123,  $course->idnumber);
 539  
 540          foreach ($modinfo->get_cms() as $cm) {
 541              $this->assertContains($cm->get_formatted_name(), $this->activitynames);
 542          }
 543  
 544          // Should be no discussions as the user that made them wasn't included.
 545          $this->assertEquals(2, count($discussions));
 546  
 547          // There should only be two users in the new course. The copier and one student.
 548          $this->assertEquals(2, count($users));
 549          $this->assertEquals($this->courseusers[2], $users[$this->courseusers[2]]->id);
 550          $this->assertEquals($this->courseusers[0], $users[$this->courseusers[0]]->id);
 551      }
 552  
 553      /*
 554       * Test course copy, not including any users (or data).
 555       */
 556      public function test_course_copy_no_data() {
 557          global $DB;
 558  
 559          // Mock up the form data.
 560          $formdata = new \stdClass;
 561          $formdata->courseid = $this->course->id;
 562          $formdata->fullname = 'copy course';
 563          $formdata->shortname = 'copy course short';
 564          $formdata->category = 1;
 565          $formdata->visible = 0;
 566          $formdata->startdate = 1582376400;
 567          $formdata->enddate = 1582386400;
 568          $formdata->idnumber = 123;
 569          $formdata->userdata = 0;
 570          $formdata->role_1 = 1;
 571          $formdata->role_3 = 3;
 572          $formdata->role_5 = 5;
 573  
 574          // Create the course copy records and associated ad-hoc task.
 575          $coursecopy = new \core_backup\copy\copy($formdata);
 576          $copyids = $coursecopy->create_copy();
 577  
 578          $courseid = $this->course->id;
 579  
 580          // We are expecting trace output during this test.
 581          $this->expectOutputRegex("/$courseid/");
 582  
 583          // Execute adhoc task.
 584          $now = time();
 585          $task = \core\task\manager::get_next_adhoc_task($now);
 586          $this->assertInstanceOf('\\core\\task\\asynchronous_copy_task', $task);
 587          $task->execute();
 588          \core\task\manager::adhoc_task_complete($task);
 589  
 590          $postrestorerec = $DB->get_record('backup_controllers', array('backupid' => $copyids['restoreid']));
 591  
 592          // Check the restored course itself.
 593          $coursecontext = context_course::instance($postrestorerec->itemid);
 594          $users = get_enrolled_users($coursecontext);
 595  
 596          get_fast_modinfo($postrestorerec->itemid, 0, true);
 597          $modinfo = get_fast_modinfo($postrestorerec->itemid);
 598          $forums = $modinfo->get_instances_of('forum');
 599          $forum = reset($forums);
 600          $discussions = forum_get_discussions($forum);
 601          $course = $modinfo->get_course();
 602  
 603          $this->assertEquals($formdata->startdate, $course->startdate);
 604          $this->assertEquals($formdata->enddate, $course->enddate);
 605          $this->assertEquals('copy course', $course->fullname);
 606          $this->assertEquals('copy course short',  $course->shortname);
 607          $this->assertEquals(0,  $course->visible);
 608          $this->assertEquals(123,  $course->idnumber);
 609  
 610          foreach ($modinfo->get_cms() as $cm) {
 611              $this->assertContains($cm->get_formatted_name(), $this->activitynames);
 612          }
 613  
 614          // Should be no discussions as the user data wasn't included.
 615          $this->assertEquals(0, count($discussions));
 616  
 617          // There should only be all users in the new course.
 618          $this->assertEquals(count($this->courseusers), count($users));
 619      }
 620  
 621      /*
 622       * Test instantiation with incomplete formdata.
 623       */
 624      public function test_malformed_instantiation() {
 625          // Mock up the form data, missing things so we get an exception.
 626          $formdata = new \stdClass;
 627          $formdata->courseid = $this->course->id;
 628          $formdata->fullname = 'copy course';
 629          $formdata->shortname = 'copy course short';
 630          $formdata->category = 1;
 631  
 632          // Expect and exception as form data is incomplete.
 633          $this->expectException(\moodle_exception::class);
 634          new \core_backup\copy\copy($formdata);
 635      }
 636  }