From 56537316f603ff8d60e57d5dc48ee88a44f21900 Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Mon, 11 Apr 2016 18:21:11 +0800 Subject: [PATCH] MDL-53719 competency: Delete content upon course and cm delete/reset --- competency/classes/api.php | 41 +++++++ competency/tests/hooks_test.php | 182 ++++++++++++++++++++++++++++++++ course/lib.php | 3 + course/reset_form.php | 2 +- lang/en/competency.php | 1 + lib/moodlelib.php | 12 +++ 6 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 competency/tests/hooks_test.php diff --git a/competency/classes/api.php b/competency/classes/api.php index fc1dd11052a7d..3cb8ae1c0b37c 100644 --- a/competency/classes/api.php +++ b/competency/classes/api.php @@ -4643,6 +4643,47 @@ public static function observe_course_completed(\core\event\course_completed $ev } } + /** + * Action to perform when a course module is deleted. + * + * Do not call this directly, this is reserved for core use. + * + * @param stdClass $cm The CM object. + * @return void + */ + public static function hook_course_module_deleted(stdClass $cm) { + global $DB; + $DB->delete_records(course_module_competency::TABLE, array('cmid' => $cm->id)); + } + + /** + * Action to perform when a course is deleted. + * + * Do not call this directly, this is reserved for core use. + * + * @param stdClass $course The course object. + * @return void + */ + public static function hook_course_deleted(stdClass $course) { + global $DB; + $DB->delete_records(course_competency::TABLE, array('courseid' => $course->id)); + $DB->delete_records(course_competency_settings::TABLE, array('courseid' => $course->id)); + $DB->delete_records(user_competency_course::TABLE, array('courseid' => $course->id)); + } + + /** + * Action to perform when a course is being reset. + * + * Do not call this directly, this is reserved for core use. + * + * @param int $courseid The course ID. + * @return void + */ + public static function hook_course_reset_competency_ratings($courseid) { + global $DB; + $DB->delete_records(user_competency_course::TABLE, array('courseid' => $courseid)); + } + /** * Manually grade a user competency. * diff --git a/competency/tests/hooks_test.php b/competency/tests/hooks_test.php new file mode 100644 index 0000000000000..568b1897e98fd --- /dev/null +++ b/competency/tests/hooks_test.php @@ -0,0 +1,182 @@ +. + +/** + * Hook tests. + * + * @package core_competency + * @copyright 2016 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use core_competency\course_competency; +use core_competency\course_module_competency; +use core_competency\user_competency_course; + +/** + * Hook tests. + * + * @package core_competency + * @copyright 2016 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_competency_hooks_testcase extends advanced_testcase { + + public function test_hook_course_deleted() { + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $ccg = $dg->get_plugin_generator('core_competency'); + + $u1 = $dg->create_user(); + + $framework = $ccg->create_framework(); + $comp1 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); + $comp2 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); + + $c1 = $dg->create_course(); + $cc1a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id]); + $cc1b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id]); + $assign1a = $dg->create_module('assign', ['course' => $c1]); + $assign1b = $dg->create_module('assign', ['course' => $c1]); + $cmc1a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1a->cmid]); + $cmc1b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1b->cmid]); + $ucc1a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id, + 'userid' => $u1->id]); + $ucc1b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id, + 'userid' => $u1->id]); + + $c2 = $dg->create_course(); + $cc2a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id]); + $cc2b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id]); + $assign2a = $dg->create_module('assign', ['course' => $c2]); + $assign2b = $dg->create_module('assign', ['course' => $c2]); + $cmc2a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2a->cmid]); + $cmc2b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2b->cmid]); + $ucc2a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id, + 'userid' => $u1->id]); + $ucc2b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id, + 'userid' => $u1->id]); + + delete_course($c1, false); + + $this->assertEquals(0, course_competency::count_records(['courseid' => $c1->id])); + $this->assertEquals(2, course_competency::count_records(['courseid' => $c2->id])); + $this->assertEquals(0, course_module_competency::count_records(['cmid' => $assign1a->cmid])); + $this->assertEquals(0, course_module_competency::count_records(['cmid' => $assign1b->cmid])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2a->cmid])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2b->cmid])); + $this->assertEquals(0, user_competency_course::count_records(['courseid' => $c1->id, 'userid' => $u1->id])); + $this->assertEquals(2, user_competency_course::count_records(['courseid' => $c2->id, 'userid' => $u1->id])); + } + + public function test_hook_course_module_deleted() { + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $ccg = $dg->get_plugin_generator('core_competency'); + + $u1 = $dg->create_user(); + + $framework = $ccg->create_framework(); + $comp1 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); + $comp2 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); + + $c1 = $dg->create_course(); + $cc1a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id]); + $cc1b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id]); + $assign1a = $dg->create_module('assign', ['course' => $c1]); + $assign1b = $dg->create_module('assign', ['course' => $c1]); + $cmc1a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1a->cmid]); + $cmc1b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1b->cmid]); + $ucc1a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id, + 'userid' => $u1->id]); + $ucc1b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id, + 'userid' => $u1->id]); + + $c2 = $dg->create_course(); + $cc2a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id]); + $cc2b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id]); + $assign2a = $dg->create_module('assign', ['course' => $c2]); + $assign2b = $dg->create_module('assign', ['course' => $c2]); + $cmc2a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2a->cmid]); + $cmc2b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2b->cmid]); + $ucc2a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id, + 'userid' => $u1->id]); + $ucc2b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id, + 'userid' => $u1->id]); + + course_delete_module($assign1b->cmid); + + $this->assertEquals(2, course_competency::count_records(['courseid' => $c1->id])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign1a->cmid])); + $this->assertEquals(0, course_module_competency::count_records(['cmid' => $assign1b->cmid])); + $this->assertEquals(2, user_competency_course::count_records(['courseid' => $c1->id])); + + $this->assertEquals(2, course_competency::count_records(['courseid' => $c2->id])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2a->cmid])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2b->cmid])); + $this->assertEquals(2, user_competency_course::count_records(['courseid' => $c2->id, 'userid' => $u1->id])); + } + + public function test_hook_course_reset_competency_ratings() { + $this->resetAfterTest(); + $dg = $this->getDataGenerator(); + $ccg = $dg->get_plugin_generator('core_competency'); + + $u1 = $dg->create_user(); + + $framework = $ccg->create_framework(); + $comp1 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); + $comp2 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); + + $c1 = $dg->create_course(); + $cc1a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id]); + $cc1b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id]); + $assign1a = $dg->create_module('assign', ['course' => $c1]); + $assign1b = $dg->create_module('assign', ['course' => $c1]); + $cmc1a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1a->cmid]); + $cmc1b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1b->cmid]); + $ucc1a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id, + 'userid' => $u1->id]); + $ucc1b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id, + 'userid' => $u1->id]); + + $c2 = $dg->create_course(); + $cc2a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id]); + $cc2b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id]); + $assign2a = $dg->create_module('assign', ['course' => $c2]); + $assign2b = $dg->create_module('assign', ['course' => $c2]); + $cmc2a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2a->cmid]); + $cmc2b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2b->cmid]); + $ucc2a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id, + 'userid' => $u1->id]); + $ucc2b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id, + 'userid' => $u1->id]); + + reset_course_userdata((object) ['id' => $c1->id, 'reset_competency_ratings' => true]); + + $this->assertEquals(2, course_competency::count_records(['courseid' => $c1->id])); + $this->assertEquals(2, course_competency::count_records(['courseid' => $c2->id])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign1a->cmid])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign1b->cmid])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2a->cmid])); + $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2b->cmid])); + $this->assertEquals(0, user_competency_course::count_records(['courseid' => $c1->id, 'userid' => $u1->id])); + $this->assertEquals(2, user_competency_course::count_records(['courseid' => $c2->id, 'userid' => $u1->id])); + } + +} diff --git a/course/lib.php b/course/lib.php index 9307e3c60ee12..5cf46bb4babc0 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1770,6 +1770,9 @@ function course_delete_module($cmid) { core_tag_tag::delete_instances('mod_' . $modulename, null, $modcontext->id); core_tag_tag::remove_all_item_tags('core', 'course_modules', $cm->id); + // Notify the competency subsystem. + \core_competency\api::hook_course_module_deleted($cm); + // Delete the context. context_helper::delete_instance(CONTEXT_MODULE, $cm->id); diff --git a/course/reset_form.php b/course/reset_form.php index 1662307f1d2f5..4fe8ddb30b463 100644 --- a/course/reset_form.php +++ b/course/reset_form.php @@ -48,7 +48,7 @@ function definition (){ $mform->addElement('checkbox', 'reset_completion', get_string('deletecompletiondata', 'completion')); $mform->addElement('checkbox', 'delete_blog_associations', get_string('deleteblogassociations', 'blog')); $mform->addHelpButton('delete_blog_associations', 'deleteblogassociations', 'blog'); - + $mform->addElement('checkbox', 'reset_competency_ratings', get_string('deletecompetencyratings', 'core_competency')); $mform->addElement('header', 'rolesheader', get_string('roles')); diff --git a/lang/en/competency.php b/lang/en/competency.php index a1b5bcfbc50d8..56aaecd5d9fba 100644 --- a/lang/en/competency.php +++ b/lang/en/competency.php @@ -37,6 +37,7 @@ $string['coursemodulecompetencyoutcome_evidence'] = 'Attach an evidence'; $string['coursemodulecompetencyoutcome_none'] = 'Do nothing'; $string['coursemodulecompetencyoutcome_recommend'] = 'Send for review'; +$string['deletecompetencyratings'] = 'Delete competency ratings'; $string['duplicateditemname'] = '{$a} (copy)'; $string['enablecompetencies'] = 'Enable competencies'; $string['enablecompetencies_desc'] = 'When unticked the competencies module will be disabled.'; diff --git a/lib/moodlelib.php b/lib/moodlelib.php index ff73eb368d4c8..b6c2998c69604 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -4815,6 +4815,9 @@ function remove_course_contents($courseid, $showfeedback = true, array $options if ($cm = get_coursemodule_from_instance($modname, $instance->id, $course->id)) { // Delete activity context questions and question categories. question_delete_activity($cm, $showfeedback); + + // Notify the competency subsystem. + \core_competency\api::hook_course_module_deleted($cm); } if (function_exists($moddelete)) { // This purges all module data in related tables, extra user prefs, settings, etc. @@ -4932,6 +4935,9 @@ function remove_course_contents($courseid, $showfeedback = true, array $options // Delete course tags. core_tag_tag::remove_all_item_tags('core', 'course', $course->id); + // Notify the competency subsystem. + \core_competency\api::hook_course_deleted($course); + // Delete calendar events. $DB->delete_records('event', array('courseid' => $course->id)); $fs->delete_area_files($coursecontext->id, 'calendar'); @@ -5118,6 +5124,12 @@ function reset_course_userdata($data) { 'item' => get_string('deletecompletiondata', 'completion'), 'error' => false); } + if (!empty($data->reset_competency_ratings)) { + \core_competency\api::hook_course_reset_competency_ratings($data->courseid); + $status[] = array('component' => $componentstr, + 'item' => get_string('deletecompetencyratings', 'core_competency'), 'error' => false); + } + $componentstr = get_string('roles'); if (!empty($data->reset_roles_overrides)) {