1330
1372
$this->assertEquals($section->id, $pagecm->section);
1333
// Move the forum and the page to a hidden section.
1334
moveto_module($pagecm, $section, $forumcm);
1336
// Reset modinfo cache.
1337
get_fast_modinfo(0, 0, true);
1339
// Verify that the the page is still hidden
1375
// Move the page inside the hidden section. Make sure it is hidden.
1376
$this->assertEquals(0, moveto_module($pagecm, $section, $forumcm));
1378
// Double check that the the page is still hidden.
1340
1379
$modinfo = get_fast_modinfo($course);
1341
1380
$pagecm = $modinfo->cms[$page->cmid];
1342
1381
$this->assertEquals($pagecm->visible, 0);
1384
public function test_course_delete_module() {
1386
$this->resetAfterTest(true);
1387
$this->setAdminUser();
1389
// Create course and modules.
1390
$course = $this->getDataGenerator()->create_course(array('numsections' => 5));
1392
// Generate an assignment with due date (will generate a course event).
1393
$assign = $this->getDataGenerator()->create_module('assign', array('duedate' => time(), 'course' => $course->id));
1395
$cm = get_coursemodule_from_instance('assign', $assign->id);
1397
// Verify context exists.
1398
$this->assertInstanceOf('context_module', context_module::instance($cm->id, IGNORE_MISSING));
1400
// Verify event assignment event has been generated.
1401
$eventcount = $DB->count_records('event', array('instance' => $assign->id, 'modulename' => 'assign'));
1402
$this->assertEquals(1, $eventcount);
1405
course_delete_module($cm->id);
1407
// Verify the context has been removed.
1408
$this->assertFalse(context_module::instance($cm->id, IGNORE_MISSING));
1410
// Verify the course_module record has been deleted.
1411
$cmcount = $DB->count_records('course_modules', array('id' => $cm->id));
1412
$this->assertEmpty($cmcount);
1414
// Verify event assignment events have been removed.
1415
$eventcount = $DB->count_records('event', array('instance' => $assign->id, 'modulename' => 'assign'));
1416
$this->assertEmpty($eventcount);
1420
* Test that triggering a course_created event works as expected.
1422
public function test_course_created_event() {
1425
$this->resetAfterTest();
1427
// Catch the events.
1428
$sink = $this->redirectEvents();
1430
// Create the course.
1431
$course = $this->getDataGenerator()->create_course();
1432
// Get course from DB for comparison.
1433
$course = $DB->get_record('course', array('id' => $course->id));
1435
// Capture the event.
1436
$events = $sink->get_events();
1439
// Validate the event.
1440
$event = $events[0];
1441
$this->assertInstanceOf('\core\event\course_created', $event);
1442
$this->assertEquals('course', $event->objecttable);
1443
$this->assertEquals($course->id, $event->objectid);
1444
$this->assertEquals(context_course::instance($course->id), $event->get_context());
1445
$this->assertEquals($course, $event->get_record_snapshot('course', $course->id));
1446
$this->assertEquals('course_created', $event->get_legacy_eventname());
1447
$this->assertEventLegacyData($course, $event);
1448
$expectedlog = array(SITEID, 'course', 'new', 'view.php?id=' . $course->id, $course->fullname . ' (ID ' . $course->id . ')');
1449
$this->assertEventLegacyLogData($expectedlog, $event);
1453
* Test that triggering a course_updated event works as expected.
1455
public function test_course_updated_event() {
1458
$this->resetAfterTest();
1461
$course = $this->getDataGenerator()->create_course();
1463
// Create a category we are going to move this course to.
1464
$category = $this->getDataGenerator()->create_category();
1466
// Create a hidden category we are going to move this course to.
1467
$categoryhidden = $this->getDataGenerator()->create_category(array('visible' => 0));
1469
// Update course and catch course_updated event.
1470
$sink = $this->redirectEvents();
1471
update_course($course);
1472
$events = $sink->get_events();
1475
// Get updated course information from the DB.
1476
$updatedcourse = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST);
1478
$event = array_shift($events);
1479
$this->assertInstanceOf('\core\event\course_updated', $event);
1480
$this->assertEquals('course', $event->objecttable);
1481
$this->assertEquals($updatedcourse->id, $event->objectid);
1482
$this->assertEquals(context_course::instance($course->id), $event->get_context());
1483
$this->assertEquals($updatedcourse, $event->get_record_snapshot('course', $event->objectid));
1484
$this->assertEquals('course_updated', $event->get_legacy_eventname());
1485
$this->assertEventLegacyData($updatedcourse, $event);
1486
$expectedlog = array($updatedcourse->id, 'course', 'update', 'edit.php?id=' . $course->id, $course->id);
1487
$this->assertEventLegacyLogData($expectedlog, $event);
1489
// Move course and catch course_updated event.
1490
$sink = $this->redirectEvents();
1491
move_courses(array($course->id), $category->id);
1492
$events = $sink->get_events();
1495
// Return the moved course information from the DB.
1496
$movedcourse = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST);
1498
$event = array_shift($events);
1499
$this->assertInstanceOf('\core\event\course_updated', $event);
1500
$this->assertEquals('course', $event->objecttable);
1501
$this->assertEquals($movedcourse->id, $event->objectid);
1502
$this->assertEquals(context_course::instance($course->id), $event->get_context());
1503
$this->assertEquals($movedcourse, $event->get_record_snapshot('course', $movedcourse->id));
1504
$this->assertEquals('course_updated', $event->get_legacy_eventname());
1505
$this->assertEventLegacyData($movedcourse, $event);
1506
$expectedlog = array($movedcourse->id, 'course', 'move', 'edit.php?id=' . $movedcourse->id, $movedcourse->id);
1507
$this->assertEventLegacyLogData($expectedlog, $event);
1509
// Move course to hidden category and catch course_updated event.
1510
$sink = $this->redirectEvents();
1511
move_courses(array($course->id), $categoryhidden->id);
1512
$events = $sink->get_events();
1515
// Return the moved course information from the DB.
1516
$movedcoursehidden = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST);
1518
$event = array_shift($events);
1519
$this->assertInstanceOf('\core\event\course_updated', $event);
1520
$this->assertEquals('course', $event->objecttable);
1521
$this->assertEquals($movedcoursehidden->id, $event->objectid);
1522
$this->assertEquals(context_course::instance($course->id), $event->get_context());
1523
$this->assertEquals($movedcoursehidden, $event->get_record_snapshot('course', $movedcoursehidden->id));
1524
$this->assertEquals('course_updated', $event->get_legacy_eventname());
1525
$this->assertEventLegacyData($movedcoursehidden, $event);
1526
$expectedlog = array($movedcoursehidden->id, 'course', 'move', 'edit.php?id=' . $movedcoursehidden->id, $movedcoursehidden->id);
1527
$this->assertEventLegacyLogData($expectedlog, $event);
1531
* Test that triggering a course_deleted event works as expected.
1533
public function test_course_deleted_event() {
1534
$this->resetAfterTest();
1536
// Create the course.
1537
$course = $this->getDataGenerator()->create_course();
1539
// Save the course context before we delete the course.
1540
$coursecontext = context_course::instance($course->id);
1542
// Catch the update event.
1543
$sink = $this->redirectEvents();
1545
// Call delete_course() which will trigger the course_deleted event and the course_content_deleted
1546
// event. This function prints out data to the screen, which we do not want during a PHPUnit test,
1547
// so use ob_start and ob_end_clean to prevent this.
1549
delete_course($course);
1552
// Capture the event.
1553
$events = $sink->get_events();
1556
// Validate the event.
1557
$event = $events[1];
1558
$this->assertInstanceOf('\core\event\course_deleted', $event);
1559
$this->assertEquals('course', $event->objecttable);
1560
$this->assertEquals($course->id, $event->objectid);
1561
$this->assertEquals($coursecontext->id, $event->contextid);
1562
$this->assertEquals($course, $event->get_record_snapshot('course', $course->id));
1563
$this->assertEquals('course_deleted', $event->get_legacy_eventname());
1564
$eventdata = $event->get_data();
1565
$this->assertSame($course->idnumber, $eventdata['other']['idnumber']);
1566
$this->assertSame($course->fullname, $eventdata['other']['fullname']);
1567
$this->assertSame($course->shortname, $eventdata['other']['shortname']);
1568
// The legacy data also passed the context in the course object.
1569
$course->context = $coursecontext;
1570
$this->assertEventLegacyData($course, $event);
1571
$expectedlog = array(SITEID, 'course', 'delete', 'view.php?id=' . $course->id, $course->fullname . '(ID ' . $course->id . ')');
1572
$this->assertEventLegacyLogData($expectedlog, $event);
1576
* Test that triggering a course_content_deleted event works as expected.
1578
public function test_course_content_deleted_event() {
1581
$this->resetAfterTest();
1583
// Create the course.
1584
$course = $this->getDataGenerator()->create_course();
1586
// Get the course from the DB. The data generator adds some extra properties, such as
1587
// numsections, to the course object which will fail the assertions later on.
1588
$course = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST);
1590
// Save the course context before we delete the course.
1591
$coursecontext = context_course::instance($course->id);
1593
// Catch the update event.
1594
$sink = $this->redirectEvents();
1596
remove_course_contents($course->id, false);
1598
// Capture the event.
1599
$events = $sink->get_events();
1602
// Validate the event.
1603
$event = $events[0];
1604
$this->assertInstanceOf('\core\event\course_content_deleted', $event);
1605
$this->assertEquals('course', $event->objecttable);
1606
$this->assertEquals($course->id, $event->objectid);
1607
$this->assertEquals($coursecontext->id, $event->contextid);
1608
$this->assertEquals($course, $event->get_record_snapshot('course', $course->id));
1609
$this->assertEquals('course_content_removed', $event->get_legacy_eventname());
1610
// The legacy data also passed the context and options in the course object.
1611
$course->context = $coursecontext;
1612
$course->options = array();
1613
$this->assertEventLegacyData($course, $event);
1617
* Test that triggering a course_category_deleted event works as expected.
1619
public function test_course_category_deleted_event() {
1620
$this->resetAfterTest();
1622
// Create a category.
1623
$category = $this->getDataGenerator()->create_category();
1625
// Save the context before it is deleted.
1626
$categorycontext = context_coursecat::instance($category->id);
1628
// Catch the update event.
1629
$sink = $this->redirectEvents();
1631
// Delete the category.
1632
$category->delete_full();
1634
// Capture the event.
1635
$events = $sink->get_events();
1638
// Validate the event.
1639
$event = $events[0];
1640
$this->assertInstanceOf('\core\event\course_category_deleted', $event);
1641
$this->assertEquals('course_categories', $event->objecttable);
1642
$this->assertEquals($category->id, $event->objectid);
1643
$this->assertEquals($categorycontext->id, $event->contextid);
1644
$this->assertEquals('course_category_deleted', $event->get_legacy_eventname());
1645
$this->assertEventLegacyData($category, $event);
1646
$expectedlog = array(SITEID, 'category', 'delete', 'index.php', $category->name . '(ID ' . $category->id . ')');
1647
$this->assertEventLegacyLogData($expectedlog, $event);
1649
// Create two categories.
1650
$category = $this->getDataGenerator()->create_category();
1651
$category2 = $this->getDataGenerator()->create_category();
1653
// Save the context before it is moved and then deleted.
1654
$category2context = context_coursecat::instance($category2->id);
1656
// Catch the update event.
1657
$sink = $this->redirectEvents();
1659
// Move the category.
1660
$category2->delete_move($category->id);
1662
// Capture the event.
1663
$events = $sink->get_events();
1666
// Validate the event.
1667
$event = $events[0];
1668
$this->assertInstanceOf('\core\event\course_category_deleted', $event);
1669
$this->assertEquals('course_categories', $event->objecttable);
1670
$this->assertEquals($category2->id, $event->objectid);
1671
$this->assertEquals($category2context->id, $event->contextid);
1672
$this->assertEquals('course_category_deleted', $event->get_legacy_eventname());
1673
$this->assertEventLegacyData($category2, $event);
1674
$expectedlog = array(SITEID, 'category', 'delete', 'index.php', $category2->name . '(ID ' . $category2->id . ')');
1675
$this->assertEventLegacyLogData($expectedlog, $event);
1679
* Test that triggering a course_restored event works as expected.
1681
public function test_course_restored_event() {
1684
// Get the necessary files to perform backup and restore.
1685
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
1686
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
1688
$this->resetAfterTest();
1690
// Set to admin user.
1691
$this->setAdminUser();
1693
// The user id is going to be 2 since we are the admin user.
1697
$course = $this->getDataGenerator()->create_course();
1699
// Create backup file and save it to the backup location.
1700
$bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE,
1701
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $userid);
1702
$bc->execute_plan();
1703
$results = $bc->get_results();
1704
$file = $results['backup_destination'];
1705
$fp = get_file_packer();
1706
$filepath = $CFG->dataroot . '/temp/backup/test-restore-course-event';
1707
$file->extract_to_pathname($fp, $filepath);
1711
// Now we want to catch the restore course event.
1712
$sink = $this->redirectEvents();
1714
// Now restore the course to trigger the event.
1715
$rc = new restore_controller('test-restore-course-event', $course->id, backup::INTERACTIVE_NO,
1716
backup::MODE_GENERAL, $userid, backup::TARGET_NEW_COURSE);
1717
$rc->execute_precheck();
1718
$rc->execute_plan();
1720
// Capture the event.
1721
$events = $sink->get_events();
1724
// Validate the event.
1725
$event = $events[0];
1726
$this->assertInstanceOf('\core\event\course_restored', $event);
1727
$this->assertEquals('course', $event->objecttable);
1728
$this->assertEquals($rc->get_courseid(), $event->objectid);
1729
$this->assertEquals(context_course::instance($rc->get_courseid())->id, $event->contextid);
1730
$this->assertEquals('course_restored', $event->get_legacy_eventname());
1731
$legacydata = (object) array(
1732
'courseid' => $rc->get_courseid(),
1733
'userid' => $rc->get_userid(),
1734
'type' => $rc->get_type(),
1735
'target' => $rc->get_target(),
1736
'mode' => $rc->get_mode(),
1737
'operation' => $rc->get_operation(),
1738
'samesite' => $rc->is_samesite()
1740
$this->assertEventLegacyData($legacydata, $event);
1742
// Destroy the resource controller since we are done using it.
1746
// Clear the time limit, otherwise PHPUnit complains.
1751
* Test that triggering a course_section_updated event works as expected.
1753
public function test_course_section_updated_event() {
1756
$this->resetAfterTest();
1758
// Create the course with sections.
1759
$course = $this->getDataGenerator()->create_course(array('numsections' => 10), array('createsections' => true));
1760
$sections = $DB->get_records('course_sections', array('course' => $course->id));
1762
$coursecontext = context_course::instance($course->id);
1764
$section = array_pop($sections);
1765
$section->name = 'Test section';
1766
$section->summary = 'Test section summary';
1767
$DB->update_record('course_sections', $section);
1769
// Trigger an event for course section update.
1770
$event = \core\event\course_section_updated::create(
1772
'objectid' => $section->id,
1773
'courseid' => $course->id,
1774
'context' => context_course::instance($course->id)
1777
$event->add_record_snapshot('course_sections', $section);
1778
// Trigger and catch event.
1779
$sink = $this->redirectEvents();
1781
$events = $sink->get_events();
1784
// Validate the event.
1785
$event = $events[0];
1786
$this->assertInstanceOf('\core\event\course_section_updated', $event);
1787
$this->assertEquals('course_sections', $event->objecttable);
1788
$this->assertEquals($section->id, $event->objectid);
1789
$this->assertEquals($course->id, $event->courseid);
1790
$this->assertEquals($coursecontext->id, $event->contextid);
1791
$expecteddesc = 'Course ' . $event->courseid . ' section ' . $event->other['sectionnum'] . ' updated by user ' . $event->userid;
1792
$this->assertEquals($expecteddesc, $event->get_description());
1793
$this->assertEquals($section, $event->get_record_snapshot('course_sections', $event->objectid));
1795
$sectionnum = $section->section;
1796
$expectedlegacydata = array($course->id, "course", "editsection", 'editsection.php?id=' . $id, $sectionnum);
1797
$this->assertEventLegacyLogData($expectedlegacydata, $event);
1800
public function test_course_integrity_check() {
1803
$this->resetAfterTest(true);
1804
$course = $this->getDataGenerator()->create_course(array('numsections' => 1),
1805
array('createsections'=>true));
1807
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
1808
array('section' => 0));
1809
$page = $this->getDataGenerator()->create_module('page', array('course' => $course->id),
1810
array('section' => 0));
1811
$quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id),
1812
array('section' => 0));
1813
$correctseq = join(',', array($forum->cmid, $page->cmid, $quiz->cmid));
1815
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1816
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1817
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1818
$this->assertEquals($correctseq, $section0->sequence);
1819
$this->assertEmpty($section1->sequence);
1820
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1821
$this->assertEquals($section0->id, $cms[$page->cmid]->section);
1822
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1823
$this->assertEmpty(course_integrity_check($course->id));
1825
// Now let's make manual change in DB and let course_integrity_check() fix it:
1827
// 1. Module appears twice in one section.
1828
$DB->update_record('course_sections', array('id' => $section0->id, 'sequence' => $section0->sequence. ','. $page->cmid));
1829
$this->assertEquals(
1830
array('Failed integrity check for course ['. $course->id.
1831
']. Sequence for course section ['. $section0->id. '] is "'.
1832
$section0->sequence. ','. $page->cmid. '", must be "'.
1833
$section0->sequence. '"'),
1834
course_integrity_check($course->id));
1835
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1836
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1837
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1838
$this->assertEquals($correctseq, $section0->sequence);
1839
$this->assertEmpty($section1->sequence);
1840
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1841
$this->assertEquals($section0->id, $cms[$page->cmid]->section);
1842
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1844
// 2. Module appears in two sections (last section wins).
1845
$DB->update_record('course_sections', array('id' => $section1->id, 'sequence' => ''. $page->cmid));
1846
// First message about double mentioning in sequence, second message about wrong section field for $page.
1847
$this->assertEquals(array(
1848
'Failed integrity check for course ['. $course->id. ']. Course module ['. $page->cmid.
1849
'] must be removed from sequence of section ['. $section0->id.
1850
'] because it is also present in sequence of section ['. $section1->id. ']',
1851
'Failed integrity check for course ['. $course->id. ']. Course module ['. $page->cmid.
1852
'] points to section ['. $section0->id. '] instead of ['. $section1->id. ']'),
1853
course_integrity_check($course->id));
1854
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1855
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1856
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1857
$this->assertEquals($forum->cmid. ','. $quiz->cmid, $section0->sequence);
1858
$this->assertEquals(''. $page->cmid, $section1->sequence);
1859
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1860
$this->assertEquals($section1->id, $cms[$page->cmid]->section);
1861
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1863
// 3. Module id is not present in course_section.sequence (integrity check with $fullcheck = false).
1864
$DB->update_record('course_sections', array('id' => $section1->id, 'sequence' => ''));
1865
$this->assertEmpty(course_integrity_check($course->id)); // Not an error!
1866
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1867
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1868
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1869
$this->assertEquals($forum->cmid. ','. $quiz->cmid, $section0->sequence);
1870
$this->assertEmpty($section1->sequence);
1871
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1872
$this->assertEquals($section1->id, $cms[$page->cmid]->section); // Not changed.
1873
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1875
// 4. Module id is not present in course_section.sequence (integrity check with $fullcheck = true).
1876
$this->assertEquals(array('Failed integrity check for course ['. $course->id. ']. Course module ['.
1877
$page->cmid. '] is missing from sequence of section ['. $section1->id. ']'),
1878
course_integrity_check($course->id, null, null, true)); // Error!
1879
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1880
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1881
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1882
$this->assertEquals($forum->cmid. ','. $quiz->cmid, $section0->sequence);
1883
$this->assertEquals(''. $page->cmid, $section1->sequence); // Yay, module added to section.
1884
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1885
$this->assertEquals($section1->id, $cms[$page->cmid]->section); // Not changed.
1886
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1888
// 5. Module id is not present in course_section.sequence and it's section is invalid (integrity check with $fullcheck = true).
1889
$DB->update_record('course_modules', array('id' => $page->cmid, 'section' => 8765));
1890
$DB->update_record('course_sections', array('id' => $section1->id, 'sequence' => ''));
1891
$this->assertEquals(array(
1892
'Failed integrity check for course ['. $course->id. ']. Course module ['. $page->cmid.
1893
'] is missing from sequence of section ['. $section0->id. ']',
1894
'Failed integrity check for course ['. $course->id. ']. Course module ['. $page->cmid.
1895
'] points to section [8765] instead of ['. $section0->id. ']'),
1896
course_integrity_check($course->id, null, null, true));
1897
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1898
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1899
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1900
$this->assertEquals($forum->cmid. ','. $quiz->cmid. ','. $page->cmid, $section0->sequence); // Module added to section.
1901
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1902
$this->assertEquals($section0->id, $cms[$page->cmid]->section); // Section changed to section0.
1903
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1905
// 6. Module is deleted from course_modules but not deleted in sequence (integrity check with $fullcheck = true).
1906
$DB->delete_records('course_modules', array('id' => $page->cmid));
1907
$this->assertEquals(array('Failed integrity check for course ['. $course->id. ']. Course module ['.
1908
$page->cmid. '] does not exist but is present in the sequence of section ['. $section0->id. ']'),
1909
course_integrity_check($course->id, null, null, true));
1910
$section0 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 0));
1911
$section1 = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 1));
1912
$cms = $DB->get_records('course_modules', array('course' => $course->id), 'id', 'id,section');
1913
$this->assertEquals($forum->cmid. ','. $quiz->cmid, $section0->sequence);
1914
$this->assertEmpty($section1->sequence);
1915
$this->assertEquals($section0->id, $cms[$forum->cmid]->section);
1916
$this->assertEquals($section0->id, $cms[$quiz->cmid]->section);
1917
$this->assertEquals(2, count($cms));
1921
* Tests for event related to course module creation.
1923
public function test_course_module_created_event() {
1925
$this->resetAfterTest();
1927
// Create an assign module.
1928
$sink = $this->redirectEvents();
1929
$modinfo = $this->create_specific_module_test('assign');
1930
$events = $sink->get_events();
1931
$event = array_pop($events);
1934
$cm = $DB->get_record('course_modules', array('id' => $modinfo->coursemodule), '*', MUST_EXIST);
1935
$mod = $DB->get_record('assign', array('id' => $modinfo->instance), '*', MUST_EXIST);
1937
// Validate event data.
1938
$this->assertInstanceOf('\core\event\course_module_created', $event);
1939
$this->assertEquals($cm->id, $event->objectid);
1940
$this->assertEquals($USER->id, $event->userid);
1941
$this->assertEquals('course_modules', $event->objecttable);
1942
$url = new moodle_url('/mod/assign/view.php', array('id' => $cm->id));
1943
$this->assertEquals($url, $event->get_url());
1945
// Test legacy data.
1946
$this->assertSame('mod_created', $event->get_legacy_eventname());
1947
$eventdata = new stdClass();
1948
$eventdata->modulename = 'assign';
1949
$eventdata->name = $mod->name;
1950
$eventdata->cmid = $cm->id;
1951
$eventdata->courseid = $cm->course;
1952
$eventdata->userid = $USER->id;
1953
$this->assertEventLegacyData($eventdata, $event);
1955
$arr = array($cm->course, "course", "add mod", "../mod/assign/view.php?id=$cm->id", "assign $cm->instance");
1956
$this->assertEventLegacyLogData($arr, $event);
1961
* Tests for event validations related to course module creation.
1963
public function test_course_module_created_event_exceptions() {
1965
$this->resetAfterTest();
1968
$modinfo = $this->create_specific_module_test('assign');
1969
$context = context_module::instance($modinfo->coursemodule);
1971
// Test not setting instanceid.
1973
$event = \core\event\course_module_created::create(array(
1974
'courseid' => $modinfo->course,
1975
'context' => $context,
1976
'objectid' => $modinfo->coursemodule,
1978
'modulename' => 'assign',
1979
'name' => 'My assignment',
1982
$this->fail("Event validation should not allow \\core\\event\\course_module_created to be triggered without
1983
other['instanceid']");
1984
} catch (coding_exception $e) {
1985
$this->assertContains("Field other['instanceid'] cannot be empty", $e->getMessage());
1988
// Test not setting modulename.
1990
$event = \core\event\course_module_created::create(array(
1991
'courseid' => $modinfo->course,
1992
'context' => $context,
1993
'objectid' => $modinfo->coursemodule,
1995
'instanceid' => $modinfo->instance,
1996
'name' => 'My assignment',
1999
$this->fail("Event validation should not allow \\core\\event\\course_module_created to be triggered without
2000
other['modulename']");
2001
} catch (coding_exception $e) {
2002
$this->assertContains("Field other['modulename'] cannot be empty", $e->getMessage());
2005
// Test not setting name.
2008
$event = \core\event\course_module_created::create(array(
2009
'courseid' => $modinfo->course,
2010
'context' => $context,
2011
'objectid' => $modinfo->coursemodule,
2013
'modulename' => 'assign',
2014
'instanceid' => $modinfo->instance,
2017
$this->fail("Event validation should not allow \\core\\event\\course_module_created to be triggered without
2019
} catch (coding_exception $e) {
2020
$this->assertContains("Field other['name'] cannot be empty", $e->getMessage());
2026
* Tests for event related to course module updates.
2028
public function test_course_module_updated_event() {
2030
$this->resetAfterTest();
2032
// Update a forum module.
2033
$sink = $this->redirectEvents();
2034
$modinfo = $this->update_specific_module_test('forum');
2035
$events = $sink->get_events();
2036
$event = array_pop($events);
2039
$cm = $DB->get_record('course_modules', array('id' => $modinfo->coursemodule), '*', MUST_EXIST);
2040
$mod = $DB->get_record('forum', array('id' => $cm->instance), '*', MUST_EXIST);
2042
// Validate event data.
2043
$this->assertInstanceOf('\core\event\course_module_updated', $event);
2044
$this->assertEquals($cm->id, $event->objectid);
2045
$this->assertEquals($USER->id, $event->userid);
2046
$this->assertEquals('course_modules', $event->objecttable);
2047
$url = new moodle_url('/mod/forum/view.php', array('id' => $cm->id));
2048
$this->assertEquals($url, $event->get_url());
2050
// Test legacy data.
2051
$this->assertSame('mod_updated', $event->get_legacy_eventname());
2052
$eventdata = new stdClass();
2053
$eventdata->modulename = 'forum';
2054
$eventdata->name = $mod->name;
2055
$eventdata->cmid = $cm->id;
2056
$eventdata->courseid = $cm->course;
2057
$eventdata->userid = $USER->id;
2058
$this->assertEventLegacyData($eventdata, $event);
2060
$arr = array($cm->course, "course", "update mod", "../mod/forum/view.php?id=$cm->id", "forum $cm->instance");
2061
$this->assertEventLegacyLogData($arr, $event);
2066
* Tests for create_from_cm method.
2068
public function test_course_module_create_from_cm() {
2069
$this->resetAfterTest();
2070
$this->setAdminUser();
2072
// Create course and modules.
2073
$course = $this->getDataGenerator()->create_course(array('numsections' => 5));
2075
// Generate an assignment.
2076
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
2078
// Get the module context.
2079
$modcontext = context_module::instance($assign->cmid);
2081
// Get course module.
2082
$cm = get_coursemodule_from_id(null, $assign->cmid, $course->id, false, MUST_EXIST);
2084
// Create an event from course module.
2085
$event = \core\event\course_module_updated::create_from_cm($cm, $modcontext);
2087
// Trigger the events.
2088
$sink = $this->redirectEvents();
2090
$events = $sink->get_events();
2091
$event2 = array_pop($events);
2094
$this->assertInstanceOf('\core\event\course_module_updated', $event);
2095
$this->assertEquals($cm->id, $event2->objectid);
2096
$this->assertEquals($modcontext, $event2->get_context());
2097
$this->assertEquals($cm->modname, $event2->other['modulename']);
2098
$this->assertEquals($cm->instance, $event2->other['instanceid']);
2099
$this->assertEquals($cm->name, $event2->other['name']);
2100
$this->assertSame('mod_updated', $event2->get_legacy_eventname());
2101
$arr = array($cm->course, "course", "update mod", "../mod/assign/view.php?id=$cm->id", "assign $cm->instance");
2102
$this->assertEventLegacyLogData($arr, $event);
2106
* Tests for event validations related to course module update.
2108
public function test_course_module_updated_event_exceptions() {
2110
$this->resetAfterTest();
2113
$modinfo = $this->create_specific_module_test('assign');
2114
$context = context_module::instance($modinfo->coursemodule);
2116
// Test not setting instanceid.
2118
$event = \core\event\course_module_updated::create(array(
2119
'courseid' => $modinfo->course,
2120
'context' => $context,
2121
'objectid' => $modinfo->coursemodule,
2123
'modulename' => 'assign',
2124
'name' => 'My assignment',
2127
$this->fail("Event validation should not allow \\core\\event\\course_module_updated to be triggered without
2128
other['instanceid']");
2129
} catch (coding_exception $e) {
2130
$this->assertContains("Field other['instanceid'] cannot be empty", $e->getMessage());
2133
// Test not setting modulename.
2135
$event = \core\event\course_module_updated::create(array(
2136
'courseid' => $modinfo->course,
2137
'context' => $context,
2138
'objectid' => $modinfo->coursemodule,
2140
'instanceid' => $modinfo->instance,
2141
'name' => 'My assignment',
2144
$this->fail("Event validation should not allow \\core\\event\\course_module_updated to be triggered without
2145
other['modulename']");
2146
} catch (coding_exception $e) {
2147
$this->assertContains("Field other['modulename'] cannot be empty", $e->getMessage());
2150
// Test not setting name.
2153
$event = \core\event\course_module_updated::create(array(
2154
'courseid' => $modinfo->course,
2155
'context' => $context,
2156
'objectid' => $modinfo->coursemodule,
2158
'modulename' => 'assign',
2159
'instanceid' => $modinfo->instance,
2162
$this->fail("Event validation should not allow \\core\\event\\course_module_updated to be triggered without
2164
} catch (coding_exception $e) {
2165
$this->assertContains("Field other['name'] cannot be empty", $e->getMessage());
2171
* Tests for event related to course module delete.
2173
public function test_course_module_deleted_event() {
2175
$this->resetAfterTest();
2177
// Create and delete a module.
2178
$sink = $this->redirectEvents();
2179
$modinfo = $this->create_specific_module_test('forum');
2180
$cm = $DB->get_record('course_modules', array('id' => $modinfo->coursemodule), '*', MUST_EXIST);
2181
course_delete_module($modinfo->coursemodule);
2182
$events = $sink->get_events();
2183
$event = array_pop($events); // delete module event.;
2186
// Validate event data.
2187
$this->assertInstanceOf('\core\event\course_module_deleted', $event);
2188
$this->assertEquals($cm->id, $event->objectid);
2189
$this->assertEquals($USER->id, $event->userid);
2190
$this->assertEquals('course_modules', $event->objecttable);
2191
$this->assertEquals(null, $event->get_url());
2192
$this->assertEquals($cm, $event->get_record_snapshot('course_modules', $cm->id));
2194
// Test legacy data.
2195
$this->assertSame('mod_deleted', $event->get_legacy_eventname());
2196
$eventdata = new stdClass();
2197
$eventdata->modulename = 'forum';
2198
$eventdata->cmid = $cm->id;
2199
$eventdata->courseid = $cm->course;
2200
$eventdata->userid = $USER->id;
2201
$this->assertEventLegacyData($eventdata, $event);
2203
$arr = array($cm->course, 'course', "delete mod", "view.php?id=$cm->course", "forum $cm->instance", $cm->id);
2204
$this->assertEventLegacyLogData($arr, $event);
2209
* Tests for event validations related to course module deletion.
2211
public function test_course_module_deleted_event_exceptions() {
2213
$this->resetAfterTest();
2216
$modinfo = $this->create_specific_module_test('assign');
2217
$context = context_module::instance($modinfo->coursemodule);
2219
// Test not setting instanceid.
2221
$event = \core\event\course_module_deleted::create(array(
2222
'courseid' => $modinfo->course,
2223
'context' => $context,
2224
'objectid' => $modinfo->coursemodule,
2226
'modulename' => 'assign',
2227
'name' => 'My assignment',
2230
$this->fail("Event validation should not allow \\core\\event\\course_module_deleted to be triggered without
2231
other['instanceid']");
2232
} catch (coding_exception $e) {
2233
$this->assertContains("Field other['instanceid'] cannot be empty", $e->getMessage());
2236
// Test not setting modulename.
2238
$event = \core\event\course_module_deleted::create(array(
2239
'courseid' => $modinfo->course,
2240
'context' => $context,
2241
'objectid' => $modinfo->coursemodule,
2243
'instanceid' => $modinfo->instance,
2244
'name' => 'My assignment',
2247
$this->fail("Event validation should not allow \\core\\event\\course_module_deleted to be triggered without
2248
other['modulename']");
2249
} catch (coding_exception $e) {
2250
$this->assertContains("Field other['modulename'] cannot be empty", $e->getMessage());
2255
* Returns a user object and its assigned new role.
2257
* @param testing_data_generator $generator
2259
* @return array The user object and the role ID
2261
protected function get_user_objects(testing_data_generator $generator, $contextid) {
2264
if (empty($USER->id)) {
2265
$user = $generator->create_user();
2266
$this->setUser($user);
2268
$roleid = create_role('Test role', 'testrole', 'Test role description');
2269
if (!is_array($contextid)) {
2270
$contextid = array($contextid);
2272
foreach ($contextid as $cid) {
2273
$assignid = role_assign($roleid, $user->id, $cid);
2275
return array($user, $roleid);
2279
* Test course move after course.
2281
public function test_course_change_sortorder_after_course() {
2284
$this->resetAfterTest(true);
2286
$generator = $this->getDataGenerator();
2287
$category = $generator->create_category();
2288
$course3 = $generator->create_course(array('category' => $category->id));
2289
$course2 = $generator->create_course(array('category' => $category->id));
2290
$course1 = $generator->create_course(array('category' => $category->id));
2291
$context = $category->get_context();
2293
list($user, $roleid) = $this->get_user_objects($generator, $context->id);
2294
$caps = course_capability_assignment::allow('moodle/category:manage', $roleid, $context->id);
2296
$courses = $category->get_courses();
2297
$this->assertInternalType('array', $courses);
2298
$this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
2299
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2300
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2302
// Test moving down.
2303
$this->assertTrue(course_change_sortorder_after_course($course1->id, $course3->id));
2304
$courses = $category->get_courses();
2305
$this->assertInternalType('array', $courses);
2306
$this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
2307
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2308
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2311
$this->assertTrue(course_change_sortorder_after_course($course1->id, $course2->id));
2312
$courses = $category->get_courses();
2313
$this->assertInternalType('array', $courses);
2314
$this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
2315
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2316
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2318
// Test moving to the top.
2319
$this->assertTrue(course_change_sortorder_after_course($course1->id, 0));
2320
$courses = $category->get_courses();
2321
$this->assertInternalType('array', $courses);
2322
$this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
2323
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2324
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2328
* Tests changing the visibility of a course.
2330
public function test_course_change_visibility() {
2333
$this->resetAfterTest(true);
2335
$generator = $this->getDataGenerator();
2336
$category = $generator->create_category();
2337
$course = $generator->create_course(array('category' => $category->id));
2339
$this->assertEquals('1', $course->visible);
2340
$this->assertEquals('1', $course->visibleold);
2342
$this->assertTrue(course_change_visibility($course->id, false));
2343
$course = $DB->get_record('course', array('id' => $course->id));
2344
$this->assertEquals('0', $course->visible);
2345
$this->assertEquals('0', $course->visibleold);
2347
$this->assertTrue(course_change_visibility($course->id, true));
2348
$course = $DB->get_record('course', array('id' => $course->id));
2349
$this->assertEquals('1', $course->visible);
2350
$this->assertEquals('1', $course->visibleold);
2354
* Tests moving the course up and down by one.
2356
public function test_course_change_sortorder_by_one() {
2359
$this->resetAfterTest(true);
2361
$generator = $this->getDataGenerator();
2362
$category = $generator->create_category();
2363
$course3 = $generator->create_course(array('category' => $category->id));
2364
$course2 = $generator->create_course(array('category' => $category->id));
2365
$course1 = $generator->create_course(array('category' => $category->id));
2367
$courses = $category->get_courses();
2368
$this->assertInternalType('array', $courses);
2369
$this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
2370
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2371
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2373
// Test moving down.
2374
$course1 = get_course($course1->id);
2375
$this->assertTrue(course_change_sortorder_by_one($course1, false));
2376
$courses = $category->get_courses();
2377
$this->assertInternalType('array', $courses);
2378
$this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
2379
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2380
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2383
$course1 = get_course($course1->id);
2384
$this->assertTrue(course_change_sortorder_by_one($course1, true));
2385
$courses = $category->get_courses();
2386
$this->assertInternalType('array', $courses);
2387
$this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
2388
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2389
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2391
// Test moving the top course up one.
2392
$course1 = get_course($course1->id);
2393
$this->assertFalse(course_change_sortorder_by_one($course1, true));
2394
// Check nothing changed.
2395
$courses = $category->get_courses();
2396
$this->assertInternalType('array', $courses);
2397
$this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
2398
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2399
$this->assertEquals(array_keys($dbcourses), array_keys($courses));
2401
// Test moving the bottom course up down.
2402
$course3 = get_course($course3->id);
2403
$this->assertFalse(course_change_sortorder_by_one($course3, false));
2404
// Check nothing changed.
2405
$courses = $category->get_courses();
2406
$this->assertInternalType('array', $courses);
2407
$this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
2408
$dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id');
2409
$this->assertEquals(array_keys($dbcourses), array_keys($courses));