diff --git a/course/lib.php b/course/lib.php index 22b9e96edb3ad..968169c6953e8 100644 --- a/course/lib.php +++ b/course/lib.php @@ -3485,6 +3485,15 @@ function duplicate_module($course, $cm, int $sectionid = null, bool $changename // The following line is to be removed in MDL-58906. course_module_update_calendar_events($newcm->modname, null, $newcm); + // Copy permission overrides to new course module. + $newcmcontext = context_module::instance($newcm->id); + $overrides = $DB->get_records('role_capabilities', ['contextid' => $cmcontext->id]); + foreach ($overrides as $override) { + $override->contextid = $newcmcontext->id; + unset($record->id); + $DB->insert_record('role_capabilities', $override); + } + // Trigger course module created event. We can trigger the event only if we know the newcmid. $newcm = get_fast_modinfo($cm->course)->get_cm($newcmid); $event = \core\event\course_module_created::create_from_cm($newcm); diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 728736f476fb4..c72851256c386 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -3046,6 +3046,43 @@ public function test_duplicate_module() { } } + /** + * Test that permissions are duplicated correctly after duplicate_module(). + * @covers ::duplicate_module + * @return void + */ + public function test_duplicate_module_permissions(): void { + global $DB; + $this->setAdminUser(); + $this->resetAfterTest(); + + // Create course and course module. + $course = self::getDataGenerator()->create_course(); + $res = self::getDataGenerator()->create_module('assign', ['course' => $course]); + $cm = get_coursemodule_from_id('assign', $res->cmid, 0, false, MUST_EXIST); + $cmcontext = \context_module::instance($cm->id); + + // Enrol student user. + $user = self::getDataGenerator()->create_user(); + $roleid = $DB->get_field('role', 'id', ['shortname' => 'student'], MUST_EXIST); + self::getDataGenerator()->enrol_user($user->id, $course->id, $roleid); + + // Add capability to original course module. + assign_capability('gradereport/grader:view', CAP_ALLOW, $roleid, $cmcontext->id); + + // Duplicate module. + $newcm = duplicate_module($course, $cm); + $newcmcontext = \context_module::instance($newcm->id); + + // Assert that user still has capability. + $this->assertTrue(has_capability('gradereport/grader:view', $newcmcontext, $user)); + + // Assert that both modules contain the same count of overrides. + $overrides = $DB->get_records('role_capabilities', ['contextid' => $cmcontext->id]); + $newoverrides = $DB->get_records('role_capabilities', ['contextid' => $newcmcontext->id]); + $this->assertEquals(count($overrides), count($newoverrides)); + } + /** * Tests that when creating or updating a module, if the availability settings * are present but set to an empty tree, availability is set to null in