diff --git a/classes/helper.php b/classes/helper.php index ba4227c..818a541 100644 --- a/classes/helper.php +++ b/classes/helper.php @@ -83,16 +83,22 @@ class helper { */ public const STUDENT_ROLE = 'student'; + /** + * Cached student role object. + * @var stdClass + */ + private static $studentrole; + /** * Add a new configuration item. * * @param int $itemid Item ID number * @param string $itemtype Item type (tag, course, category). * @param string $itemname Item name. - * @param array $courses Course to set up enrolment method. If not set, the no enrolment method will be created. + * @param array $courseids Course to set up enrolment method. If not set, the no enrolment method will be created. * @return void */ - public static function add_item(int $itemid, string $itemtype, string $itemname, array $courses = []): void { + public static function add_item(int $itemid, string $itemtype, string $itemname, array $courseids = []): void { $cohort = self::get_cohort_by_item($itemid, $itemtype); if (empty($cohort)) { @@ -114,15 +120,8 @@ public static function add_item(int $itemid, string $itemtype, string $itemname, self::add_rule($cohort, $itemtype); // Add a tag to a custom profile field. self::add_profile_field_item($itemtype, $itemname); - - // Create enrolment method for the cohort for a given course. - if (!empty($courses)) { - foreach ($courses as $course) { - if (!empty($course)) { - self::add_enrolment_method($course, $cohort); - } - } - } + // Add enrolment method for given course ids. + self::add_enrolment_method($cohort, $courseids); } /** @@ -151,6 +150,8 @@ public static function remove_item(int $itemid, string $itemtype, string $itemna cohort_delete_cohort($cohort); // Delete tag value from custom profile field list. self::delete_profile_field_item($itemtype, $itemname); + // Clean up presets. + self::remove_item_from_presets($itemid, $itemtype); // Clean up user data? } } @@ -187,7 +188,6 @@ public static function rename_item(int $itemid, string $itemtype, string $newnam // Update custom profile field. self::update_profile_field_item($itemtype, $oldname, $newname); - // Update users data. TODO: move to adhoc task. $field = $DB->get_record('user_info_field', ['shortname' => $itemtype]); if ($field) { @@ -244,26 +244,34 @@ public static function get_cohort_by_item(int $itemid, string $itemtype): ?stdCl /** * Helper method to add enrolment method to a course. * - * @param stdClass $course Course. * @param stdClass $cohort Cohort. + * @param array $courseids A list of course ids. * * @return void */ - public static function add_enrolment_method(stdClass $course, stdClass $cohort): void { + public static function add_enrolment_method(stdClass $cohort, array $courseids): void { global $DB; $studentrole = self::get_student_role(); - $fields = [ - 'enrol' => 'cohort', - 'customint1' => $cohort->id, - 'roleid' => $studentrole->id, - 'courseid' => $course->id, - ]; + if (!empty($courseids)) { + list($sql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED); + $select = 'id ' . $sql; + $courses = $DB->get_records_select('course', $select, $params); - if (!$DB->record_exists('enrol', $fields)) { - $enrol = enrol_get_plugin('cohort'); - $enrol->add_instance($course, $fields); + foreach ($courses as $course) { + $fields = [ + 'enrol' => 'cohort', + 'customint1' => $cohort->id, + 'roleid' => $studentrole->id, + 'courseid' => $course->id, + ]; + + if (!$DB->record_exists('enrol', $fields)) { + $enrol = enrol_get_plugin('cohort'); + $enrol->add_instance($course, $fields); + } + } } } @@ -464,10 +472,14 @@ public static function add_rule(stdClass $cohort, string $fieldshortname): void * * @return stdClass */ - public static function get_student_role(): stdClass { + private static function get_student_role(): stdClass { global $DB; - return $DB->get_record('role', ['shortname' => self::STUDENT_ROLE]); + if (empty(self::$studentrole)) { + self::$studentrole = $DB->get_record('role', ['shortname' => self::STUDENT_ROLE]); + } + + return self::$studentrole; } /** @@ -505,13 +517,15 @@ public static function update_course_category(int $courseid, int $newcategoryid) if ($type == self::ITEM_TYPE_CATEGORY && !empty($oldcategoryidid)) { self::remove_enrolment_method($oldcategoryidid, self::ITEM_TYPE_CATEGORY, $courseid); + $presets = self::get_presets_by_item($oldcategoryidid, self::ITEM_TYPE_CATEGORY); + self::remove_presets_enrolment_method($presets); } } $cohort = self::get_cohort_by_item($newcategoryid, self::ITEM_TYPE_CATEGORY); if ($cohort) { - $course = get_course($courseid); - self::add_enrolment_method($course, $cohort); + self::add_enrolment_method($cohort, [$courseid]); + self::add_presets_enrolment_method($newcategoryid, self::ITEM_TYPE_CATEGORY, [$courseid]); } } @@ -610,4 +624,149 @@ public static function get_courses_by_tags(array $tagids): array { return $DB->get_records_sql($sql, $params); } + + /** + * A tiny helper method to convert list of items from string to array. + * + * @param string|null $data + * @return array + */ + public static function explode_data(?string $data): array { + return !empty($data) ? explode(',', $data) : []; + } + + /** + * Get list of presets by item type and ID. + * + * @param int $itemid Item ID. + * @param string $itemtype Itenm type. + * + * @return preset[] + */ + public static function get_presets_by_item(int $itemid, string $itemtype): array { + $results = []; + + if (in_array($itemtype, self::get_field_types())) { + foreach (preset::get_records() as $preset) { + if (in_array($itemid, self::explode_data($preset->get($itemtype)))) { + $results[$preset->get('id')] = $preset; + } + } + } + + return $results; + } + + /** + * Get a list of field types. + * + * @return string[] + */ + public static function get_field_types(): array { + return [self::ITEM_TYPE_CATEGORY, self::ITEM_TYPE_COURSE, self::ITEM_TYPE_TAG]; + } + + /** + * Get list of course IDs for a given preset. + * + * @param preset $preset Preset + * @return array + */ + public static function get_course_ids_from_preset(preset $preset): array { + $courseids = []; + + if (!empty($preset->get('category'))) { + $catcourses = array_keys( + self::get_courses_by_categories(explode(',', $preset->get('category'))) + ); + + $courseids = array_unique(array_merge($courseids, $catcourses)); + } + + if (!empty($preset->get('course'))) { + $courses = explode(',', $preset->get('course')); + $courseids = array_unique(array_merge($courseids, $courses)); + } + + if (!empty($preset->get('tag'))) { + $tagcourses = array_keys( + self::get_courses_by_tags(explode(',', $preset->get('tag'))) + ); + $courseids = array_values(array_unique(array_merge($courseids, $tagcourses))); + } + + return $courseids; + } + + /** + * Removes a given item from presets. + * + * @param int $itemid Item ID. + * @param string $itemtype Item type (e.g. category, course or tag). + */ + private static function remove_item_from_presets(int $itemid, string $itemtype): void { + $presets = self::get_presets_by_item($itemid, $itemtype); + + foreach ($presets as $preset) { + $items = self::explode_data($preset->get($itemtype)); + if (($key = array_search($itemid, $items)) !== false) { + unset($items[$key]); + } + $preset->set($itemtype, implode(',', $items)); + $preset->save(); + } + + self::remove_presets_enrolment_method($presets); + } + + /** + * @param array $presets + */ + public static function remove_presets_enrolment_method(array $presets): void { + global $DB; + + foreach ($presets as $preset) { + $cohort = self::get_cohort_by_item($preset->get('id'), self::ITEM_TYPE_PRESET); + if ($cohort) { + $presetcourses = self::get_course_ids_from_preset($preset); + $studentrole = self::get_student_role(); + + $fields = [ + 'enrol' => 'cohort', + 'customint1' => $cohort->id, + 'roleid' => $studentrole->id, + ]; + + $instances = $DB->get_records('enrol', $fields); + + if ($instances) { + $enrol = enrol_get_plugin('cohort'); + foreach ($instances as $instance) { + // If enrolment instance belongs to a course that is no longer part of preset, + // them delete this enrolment instance. + if (!in_array($instance->courseid, $presetcourses)) { + $enrol->delete_instance($instance); + } + } + } + } + } + } + + /** + * Adds presets enrolment method for a given item. + * + * @param int $itemid Item ID. + * @param string $itemtype Item type. + * @param array $courseids Courses to add enrolment method to. + */ + public static function add_presets_enrolment_method(int $itemid, string $itemtype, array $courseids = []): void { + $presets = helper::get_presets_by_item($itemid, $itemtype); + foreach ($presets as $preset) { + $cohort = helper::get_cohort_by_item($preset->get('id'), helper::ITEM_TYPE_PRESET); + if (!empty($cohort)) { + helper::add_enrolment_method($cohort, $courseids); + } + } + } } diff --git a/classes/observer.php b/classes/observer.php index 6099148..b0b8f93 100644 --- a/classes/observer.php +++ b/classes/observer.php @@ -225,7 +225,6 @@ public static function course_category_updated(course_category_updated $event): * @param course_category_deleted $event The event. */ public static function course_category_deleted(course_category_deleted $event): void { - $categoryid = $event->objectid; $categoryname = $event->other['name']; @@ -242,34 +241,13 @@ public static function course_category_deleted(course_category_deleted $event): * @param preset_created $event The event. */ public static function preset_created(preset_created $event): void { - $courseids = []; - - if (!empty($event->other['categories'])) { - $catcourses = array_keys( - helper::get_courses_by_categories(explode(',', $event->other['categories'])) - ); - - $courseids = array_unique(array_merge($courseids, $catcourses)); - } - - if (!empty($event->other['courses'])) { - $courses = explode(',', $event->other['courses']); - $courseids = array_unique(array_merge($courseids, $courses)); - - } - - if (!empty($event->other['tags'])) { - $tagcourses = array_keys( - helper::get_courses_by_tags(explode(',', $event->other['tags'])) - ); - $courseids = array_values(array_unique(array_merge($courseids, $tagcourses))); - } + $preset = preset::get_record(['id' => $event->other['presetid']]); self::queue_adhoc_task('add_item', [ - 'itemid' => $event->other['presetid'], + 'itemid' => $preset->get('id'), 'itemtype' => helper::ITEM_TYPE_PRESET, - 'itemname' => $event->other['presetname'], - 'courseids' => $courseids, + 'itemname' => $preset->get('name'), + 'courseids' => helper::get_course_ids_from_preset($preset), ]); } diff --git a/classes/preset_form.php b/classes/preset_form.php index 5bc651b..624f2f4 100644 --- a/classes/preset_form.php +++ b/classes/preset_form.php @@ -47,7 +47,7 @@ protected function definition() { $this->_form->addElement('static', 'error', ''); - foreach ($this->get_field_types() as $type) { + foreach (helper::get_field_types() as $type) { $methodname = 'get_' . $type . '_options'; $this->_form->addElement( 'autocomplete', @@ -59,15 +59,6 @@ protected function definition() { } } - /** - * Get a list of field types. - * - * @return string[] - */ - protected function get_field_types(): array { - return ['category', 'course', 'tag']; - } - /** * Gets categories options. * @@ -132,13 +123,13 @@ public function validation($data, $files) { $errors = parent::validation($data, $files); $empty = 0; - foreach ($this->get_field_types() as $type) { + foreach (helper::get_field_types() as $type) { if (empty($data[$type])) { $empty++; } } - if ($empty == count($this->get_field_types())) { + if ($empty == count(helper::get_field_types())) { $errors['error'] = get_string('mustselectentities', 'tool_enrolprofile'); } @@ -178,7 +169,7 @@ public function process_dynamic_submission(): \stdClass { $preset = new preset(); } - foreach ($this->get_field_types() as $type) { + foreach (helper::get_field_types() as $type) { if (!empty($data->$type)) { $data->$type = implode(',', $data->$type); } else { @@ -197,7 +188,7 @@ public function process_dynamic_submission(): \stdClass { 'presetname' => $preset->get('name'), ]; - foreach ($this->get_field_types() as $type) { + foreach (helper::get_field_types() as $type) { $other[$type] = $data->$type; $other['old' . $type] = $olddata->$type; } @@ -208,7 +199,7 @@ public function process_dynamic_submission(): \stdClass { 'other' => $other, ])->trigger(); } else { - foreach ($this->get_field_types() as $type) { + foreach (helper::get_field_types() as $type) { $other['old' . $type] = $olddata->$type; } preset_updated::create([ diff --git a/classes/task/add_item.php b/classes/task/add_item.php index 8c8f748..3f1006b 100644 --- a/classes/task/add_item.php +++ b/classes/task/add_item.php @@ -35,7 +35,6 @@ class add_item extends adhoc_task { public function execute() { global $DB; - $courses = []; $data = $this->get_custom_data(); helper::validate_task_custom_data($data); @@ -47,13 +46,13 @@ public function execute() { $data->courseids = [$data->courseid]; } - if (!empty($data->courseids) && is_array($data->courseids)) { - list($sql, $params) = $DB->get_in_or_equal($data->courseids, SQL_PARAMS_NAMED); - $select = 'id ' . $sql; - $courses = $DB->get_records_select('course', $select, $params); + if (empty($data->courseids)) { + $data->courseids = []; } - helper::add_item($data->itemid, $data->itemtype, $data->itemname, $courses); + helper::add_item($data->itemid, $data->itemtype, $data->itemname, $data->courseids); + helper::add_presets_enrolment_method($data->itemid, $data->itemtype, $data->courseids); + $transaction->allow_commit(); } catch (Exception $exception) { $transaction->rollback($exception); diff --git a/classes/task/remove_enrolment_method.php b/classes/task/remove_enrolment_method.php index 78f519c..cbeffb0 100644 --- a/classes/task/remove_enrolment_method.php +++ b/classes/task/remove_enrolment_method.php @@ -42,6 +42,10 @@ public function execute() { try { helper::remove_enrolment_method($data->itemid, $data->itemtype, $data->courseid); + + $presets = helper::get_presets_by_item($data->itemid, $data->itemtype); + helper::remove_presets_enrolment_method($presets); + $transaction->allow_commit(); } catch (Exception $exception) { $transaction->rollback($exception); diff --git a/classes/task/update_preset_data.php b/classes/task/update_preset_data.php index ecfceb0..53198ee 100644 --- a/classes/task/update_preset_data.php +++ b/classes/task/update_preset_data.php @@ -102,8 +102,8 @@ private function validate_custom_data(stdClass $data): void { * @param stdClass $data Categories data. */ private function process_categories(stdClass $data): void { - $categories = $this->explode_data($data->categories); - $oldcategories = $this->explode_data($data->oldcategories); + $categories = helper::explode_data($data->categories); + $oldcategories = helper::explode_data($data->oldcategories); $this->update_course_lists($categories, $oldcategories, 'get_courses_by_categories'); } @@ -114,8 +114,8 @@ private function process_categories(stdClass $data): void { * @param stdClass $data Courses data. */ private function process_courses(stdClass $data): void { - $courses = $this->explode_data($data->courses); - $oldcourses = $this->explode_data($data->oldcourses); + $courses = helper::explode_data($data->courses); + $oldcourses = helper::explode_data($data->oldcourses); $this->update_course_lists($courses, $oldcourses); } @@ -126,22 +126,12 @@ private function process_courses(stdClass $data): void { * @param \stdClass $data Tags data. */ private function process_tags(stdClass $data): void { - $tags = $this->explode_data($data->tags); - $oldtags = $this->explode_data($data->oldtags); + $tags = helper::explode_data($data->tags); + $oldtags = helper::explode_data($data->oldtags); $this->update_course_lists($tags, $oldtags, 'get_courses_by_tags'); } - /** - * A tiny helper method to convert list of items from string to array. - * - * @param string $data - * @return array - */ - private function explode_data(string $data): array { - return !empty($data) ? explode(',', $data) : []; - } - /** * Update list of courses based on new and old items. * @@ -175,9 +165,6 @@ private function update_enrolments(int $itemid, string $itemtype): void { helper::remove_enrolment_method($itemid, $itemtype, $courseid); } - foreach ($this->coursesadd as $courseid) { - $course = get_course($courseid); - helper::add_enrolment_method($course, $this->cohort); - } + helper::add_enrolment_method($this->cohort, $this->coursesadd); } } diff --git a/tests/helper_test.php b/tests/helper_test.php index 89ff3b4..8417111 100644 --- a/tests/helper_test.php +++ b/tests/helper_test.php @@ -234,4 +234,95 @@ public function test_validate_task_custom_data(array $data, array $fields, strin helper::validate_task_custom_data((object)$data, $fields); } + + /** + * Testing getting presets by item + */ + public function test_get_presets_by_item() { + $this->resetAfterTest(); + + $category1 = $this->getDataGenerator()->create_category(); + $category2 = $this->getDataGenerator()->create_category(); + + $course1 = $this->getDataGenerator()->create_course(); + $course2 = $this->getDataGenerator()->create_course(); + + $tag1 = $this->getDataGenerator()->create_tag(); + $tag2 = $this->getDataGenerator()->create_tag(); + + $preset1 = new preset(); + $preset1->set('name', 'Test preset 1'); + $preset1->set('category', implode(',', [$category1->id])); + $preset1->set('course', implode(',', [$course1->id])); + $preset1->set('tag', implode(',', [$tag1->id])); + $preset1->save(); + + $preset2 = new preset(); + $preset2->set('name', 'Test preset 2'); + $preset2->set('category', implode(',', [$category2->id])); + $preset2->set('course', implode(',', [$course2->id])); + $preset2->set('tag', implode(',', [$tag2->id])); + $preset2->save(); + + $preset3 = new preset(); + $preset3->set('name', 'Test preset 3'); + $preset3->set('category', implode(',', [$category1->id])); + $preset3->save(); + + $preset4 = new preset(); + $preset4->set('name', 'Test preset 4'); + $preset4->set('course', implode(',', [$course1->id])); + $preset4->save(); + + $preset5 = new preset(); + $preset5->set('name', 'Test preset 5'); + $preset5->set('tag', implode(',', [$tag2->id])); + $preset5->save(); + + $preset6 = new preset(); + $preset6->set('name', 'Test preset 6'); + $preset6->set('category', implode(',', [$category1->id, $category2->id])); + $preset6->set('course', implode(',', [$course1->id, $course2->id])); + $preset6->set('tag', implode(',', [$tag1->id, $tag2->id])); + $preset6->save(); + + $results = helper::get_presets_by_item($category1->id, helper::ITEM_TYPE_CATEGORY); + $this->assertCount(3, $results); + $this->assertArrayHasKey($preset1->get('id'), $results); + $this->assertArrayHasKey($preset3->get('id'), $results); + $this->assertArrayHasKey($preset6->get('id'), $results); + + $results = helper::get_presets_by_item($category2->id, helper::ITEM_TYPE_CATEGORY); + $this->assertCount(2, $results); + $this->assertArrayHasKey($preset2->get('id'), $results); + $this->assertArrayHasKey($preset6->get('id'), $results); + + $results = helper::get_presets_by_item($course1->id, helper::ITEM_TYPE_COURSE); + $this->assertCount(3, $results); + $this->assertArrayHasKey($preset1->get('id'), $results); + $this->assertArrayHasKey($preset4->get('id'), $results); + $this->assertArrayHasKey($preset6->get('id'), $results); + + $results = helper::get_presets_by_item($course2->id, helper::ITEM_TYPE_COURSE); + $this->assertCount(2, $results); + $this->assertArrayHasKey($preset2->get('id'), $results); + $this->assertArrayHasKey($preset6->get('id'), $results); + + $results = helper::get_presets_by_item($tag1->id, helper::ITEM_TYPE_TAG); + $this->assertCount(2, $results); + $this->assertArrayHasKey($preset1->get('id'), $results); + $this->assertArrayHasKey($preset6->get('id'), $results); + + $results = helper::get_presets_by_item($tag2->id, helper::ITEM_TYPE_TAG); + $this->assertCount(3, $results); + $this->assertArrayHasKey($preset2->get('id'), $results); + $this->assertArrayHasKey($preset5->get('id'), $results); + $this->assertArrayHasKey($preset6->get('id'), $results); + + $results = helper::get_presets_by_item(77777, helper::ITEM_TYPE_TAG); + $this->assertCount(0, $results); + + $results = helper::get_presets_by_item($preset1->get('id'), helper::ITEM_TYPE_PRESET); + $this->assertCount(0, $results); + } } diff --git a/tests/observer_test.php b/tests/observer_test.php index da26218..8e90395 100644 --- a/tests/observer_test.php +++ b/tests/observer_test.php @@ -147,6 +147,27 @@ protected function execute_tasks(): void { } } + /** + * Trigger preset_created event. + * + * @param preset $preset + */ + protected function trigger_preset_created(preset $preset): void { + preset_created::create([ + 'context' => system::instance(), + 'other' => [ + 'presetid' => $preset->get('id'), + 'presetname' => $preset->get('name'), + 'categories' => $preset->get('category'), + 'oldcategories' => null, + 'courses' => $preset->get('course'), + 'oldcourses' => null, + 'tags' => $preset->get('tag'), + 'oldtags' => null + ] + ])->trigger(); + } + /** * Check logic when adding a tag. */ @@ -931,20 +952,7 @@ public function test_preset_logic() { $preset->set('category', implode(',', [$category1->id])); $preset->save(); - preset_created::create([ - 'context' => system::instance(), - 'other' => [ - 'presetid' => $preset->get('id'), - 'presetname' => $preset->get('name'), - 'categories' => $preset->get('category'), - 'oldcategories' => null, - 'courses' => $preset->get('course'), - 'oldcourses' => null, - 'tags' => $preset->get('tag'), - 'oldtags' => null, - ] - ])->trigger(); - + $this->trigger_preset_created($preset); $this->execute_tasks(); $presetcohort = $DB->get_record('cohort', ['name' => $presetname]); @@ -991,21 +999,7 @@ public function test_preset_logic() { $preset->set('name', $presetname); $preset->set('course', implode(',', [$course11->id, $course22->id, $course31->id])); $preset->save(); - - preset_created::create([ - 'context' => system::instance(), - 'other' => [ - 'presetid' => $preset->get('id'), - 'presetname' => $preset->get('name'), - 'categories' => $preset->get('category'), - 'oldcategories' => null, - 'courses' => $preset->get('course'), - 'oldcourses' => null, - 'tags' => $preset->get('tag'), - 'oldtags' => null, - ] - ])->trigger(); - + $this->trigger_preset_created($preset); $this->execute_tasks(); $presetcohort = $DB->get_record('cohort', ['name' => $presetname]); @@ -1053,20 +1047,7 @@ public function test_preset_logic() { $preset->set('tag', implode(',', [$tag1->id, $tag2->id, $tag4->id])); $preset->save(); - preset_created::create([ - 'context' => system::instance(), - 'other' => [ - 'presetid' => $preset->get('id'), - 'presetname' => $preset->get('name'), - 'categories' => $preset->get('category'), - 'oldcategories' => null, - 'courses' => $preset->get('course'), - 'oldcourses' => null, - 'tags' => $preset->get('tag'), - 'oldtags' => null, - ] - ])->trigger(); - + $this->trigger_preset_created($preset); $this->execute_tasks(); $presetcohort = $DB->get_record('cohort', ['name' => $presetname]); @@ -1116,20 +1097,7 @@ public function test_preset_logic() { $preset->set('tag', implode(',', [$tag1->id, $tag5->id])); $preset->save(); - preset_created::create([ - 'context' => system::instance(), - 'other' => [ - 'presetid' => $preset->get('id'), - 'presetname' => $preset->get('name'), - 'categories' => $preset->get('category'), - 'oldcategories' => null, - 'courses' => $preset->get('course'), - 'oldcourses' => null, - 'tags' => $preset->get('tag'), - 'oldtags' => null - ] - ])->trigger(); - + $this->trigger_preset_created($preset); $this->execute_tasks(); $presetcohort = $DB->get_record('cohort', ['name' => $presetname]); @@ -1273,4 +1241,383 @@ public function test_preset_logic() { $DB->get_record('enrol', ['courseid' => $course32->id, 'enrol' => 'cohort', 'customint1' => $presetcohortid]) ); } + + /** + * Test preset enrolment method added when tag added to a course. + */ + public function test_preset_enrolment_added_when_tag_added() { + global $DB; + + $category = $this->getDataGenerator()->create_category(); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + $tag = $this->getDataGenerator()->create_tag(); + + $preset1name = 'Test preset 1'; + $preset1 = new preset(); + $preset1->set('name', $preset1name); + $preset1->set('tag', implode(',', [$tag->id])); + $preset1->save(); + + $this->trigger_preset_created($preset1); + + $preset2name = 'Test preset 2'; + $preset2 = new preset(); + $preset2->set('name', $preset2name); + $preset2->set('tag', implode(',', [$tag->id])); + $preset2->save(); + + $this->trigger_preset_created($preset2); + + core_tag_tag::set_item_tags('core', 'course', $course->id, course::instance($course->id), [$tag->rawname]); + $this->execute_tasks(); + + $preset1cohort = $DB->get_record('cohort', ['name' => $preset1name]); + $this->assertNotEmpty($preset1cohort); + + $preset2cohort = $DB->get_record('cohort', ['name' => $preset2name]); + $this->assertNotEmpty($preset2cohort); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + } + + /** + * Test preset enrolment method added when tag added to a course. + */ + public function test_preset_enrolment_deleted_when_tag_deleted() { + global $DB; + + $category = $this->getDataGenerator()->create_category(); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + $tag = $this->getDataGenerator()->create_tag(); + + $preset1name = 'Test preset 1'; + $preset1 = new preset(); + $preset1->set('name', $preset1name); + $preset1->set('tag', implode(',', [$tag->id])); + $preset1->save(); + $this->trigger_preset_created($preset1); + + // Preset 2 has this course as part of course items. + // This should keep preset cohort after the tag is deleted. + $preset2name = 'Test preset 2'; + $preset2 = new preset(); + $preset2->set('name', $preset2name); + $preset2->set('course', implode(',', [$course->id])); + $preset2->set('tag', implode(',', [$tag->id])); + $preset2->save(); + $this->trigger_preset_created($preset2); + + // Preset 3 has this course as part of category items. + // This should keep preset cohort after the tag is deleted. + $preset2name = 'Test preset 3'; + $preset2 = new preset(); + $preset2->set('name', $preset2name); + $preset2->set('category', implode(',', [$category->id])); + $preset2->set('tag', implode(',', [$tag->id])); + $preset2->save(); + $this->trigger_preset_created($preset2); + + core_tag_tag::set_item_tags('core', 'course', $course->id, course::instance($course->id), [$tag->rawname]); + $this->execute_tasks(); + + $preset1cohort = $DB->get_record('cohort', ['name' => $preset1name]); + $this->assertNotEmpty($preset1cohort); + + $preset2cohort = $DB->get_record('cohort', ['name' => $preset2name]); + $this->assertNotEmpty($preset2cohort); + + $preset3cohort = $DB->get_record('cohort', ['name' => $preset2name]); + $this->assertNotEmpty($preset3cohort); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + + core_tag_tag::delete_tags([$tag->id]); + $this->execute_tasks(); + + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + // Preset 2 has this course as part of course items. Should kee[ enrolment. + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + + // Preset 3 has this course as part of category items. Should keep enrolment. + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + } + + /** + * Test preset enrolment method added when tag added to a course. + */ + public function test_preset_enrolment_deleted_when_tag_removed() { + global $DB; + + $category = $this->getDataGenerator()->create_category(); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + $tag = $this->getDataGenerator()->create_tag(); + + $preset1name = 'Test preset 1'; + $preset1 = new preset(); + $preset1->set('name', $preset1name); + $preset1->set('tag', implode(',', [$tag->id])); + $preset1->save(); + $this->trigger_preset_created($preset1); + + // Preset 2 has this course as part of course items. + // This should keep preset cohort after the tag is deleted. + $preset2name = 'Test preset 2'; + $preset2 = new preset(); + $preset2->set('name', $preset2name); + $preset2->set('course', implode(',', [$course->id])); + $preset2->set('tag', implode(',', [$tag->id])); + $preset2->save(); + $this->trigger_preset_created($preset2); + + // Preset 3 has this course as part of category items. + // This should keep preset cohort after the tag is deleted. + $preset2name = 'Test preset 3'; + $preset2 = new preset(); + $preset2->set('name', $preset2name); + $preset2->set('category', implode(',', [$category->id])); + $preset2->set('tag', implode(',', [$tag->id])); + $preset2->save(); + $this->trigger_preset_created($preset2); + + core_tag_tag::set_item_tags('core', 'course', $course->id, course::instance($course->id), [$tag->rawname]); + $this->execute_tasks(); + + $preset1cohort = $DB->get_record('cohort', ['name' => $preset1name]); + $this->assertNotEmpty($preset1cohort); + + $preset2cohort = $DB->get_record('cohort', ['name' => $preset2name]); + $this->assertNotEmpty($preset2cohort); + + $preset3cohort = $DB->get_record('cohort', ['name' => $preset2name]); + $this->assertNotEmpty($preset3cohort); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + + core_tag_tag::remove_item_tag('core', 'course', $course->id, $tag->rawname); + $this->execute_tasks(); + + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + // Preset 2 has this course as part of course items. Should kee[ enrolment. + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + + // Preset 3 has this course as part of category items. Should keep enrolment. + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + } + + /** + * Test category preset enrolment method when course created. + */ + public function test_preset_enrolment_added_when_course_created() { + global $DB; + + $category = $this->getDataGenerator()->create_category(); + + $preset1name = 'Test preset 1'; + $preset1 = new preset(); + $preset1->set('name', $preset1name); + $preset1->set('category', implode(',', [$category->id])); + $preset1->save(); + + $this->trigger_preset_created($preset1); + $this->execute_tasks(); + + $preset1cohort = $DB->get_record('cohort', ['name' => $preset1name]); + $this->assertNotEmpty($preset1cohort); + + $course1 = $this->getDataGenerator()->create_course(['category' => $category->id]); + $course2 = $this->getDataGenerator()->create_course(['category' => $category->id]); + $course3 = $this->getDataGenerator()->create_course(); + + $this->execute_tasks(); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course3->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + } + + /** + * Test preset enrolment method deleted when course deleted. + */ + public function test_preset_enrolment_deleted_when_category_deleted() { + global $DB; + + $category = $this->getDataGenerator()->create_category(); + + $preset1name = 'Test preset 1'; + $preset1 = new preset(); + $preset1->set('name', $preset1name); + $preset1->set('category', implode(',', [$category->id])); + $preset1->save(); + + $this->trigger_preset_created($preset1); + $this->execute_tasks(); + + $preset1cohort = $DB->get_record('cohort', ['name' => $preset1name]); + $this->assertNotEmpty($preset1cohort); + + $course1 = $this->getDataGenerator()->create_course(['category' => $category->id]); + $course2 = $this->getDataGenerator()->create_course(['category' => $category->id]); + $course3 = $this->getDataGenerator()->create_course(); + + $this->execute_tasks(); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course3->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + } + + /** + * Check logic when moving a course to a different category. + */ + public function test_preset_enrolment_updated_course_moved_to_different_category(): void { + global $DB; + + $category1 = $this->getDataGenerator()->create_category(); + $category2 = $this->getDataGenerator()->create_category(); + $course1 = $this->getDataGenerator()->create_course(['category' => $category1->id]); + $course2 = $this->getDataGenerator()->create_course(['category' => $category1->id]); + + $preset1name = 'Test preset 1'; + $preset1 = new preset(); + $preset1->set('name', $preset1name); + $preset1->set('category', implode(',', [$category1->id])); + $preset1->save(); + $this->trigger_preset_created($preset1); + + $preset2name = 'Test preset 2'; + $preset2 = new preset(); + $preset2->set('name', $preset2name); + $preset2->set('category', implode(',', [$category2->id])); + $preset2->save(); + $this->trigger_preset_created($preset2); + + $preset3name = 'Test preset 3'; + $preset3 = new preset(); + $preset3->set('name', $preset3name); + $preset3->set('course', implode(',', [$course2->id])); + $preset3->set('category', implode(',', [$category2->id])); + $preset3->save(); + $this->trigger_preset_created($preset3); + $this->execute_tasks(); + + $preset1cohort = $DB->get_record('cohort', ['name' => $preset1name]); + $this->assertNotEmpty($preset1cohort); + + $preset2cohort = $DB->get_record('cohort', ['name' => $preset2name]); + $this->assertNotEmpty($preset2cohort); + + $preset3cohort = $DB->get_record('cohort', ['name' => $preset3name]); + $this->assertNotEmpty($preset3cohort); + + // Course 1 should have preset 1 enrolment as it has category 1. + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + + // Course 2 should have preset 1 enrolment as it has category 1 and preset 3 as + // it has course 2. + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + + $course1->category = $category2->id; + update_course($course1); + + $course2->category = $category2->id; + update_course($course2); + + $this->execute_tasks(); + + // After changing category course 1 should have preset 2 and preset 3 enrolment + // as it has category 2. + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + + // After changing category course 2 should have preset 2 and preset 3 enrolment + // as it has category 2. + $this->assertEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset1cohort->id]) + ); + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset2cohort->id]) + ); + $this->assertNotEmpty( + $DB->get_record('enrol', ['courseid' => $course2->id, 'enrol' => 'cohort', 'customint1' => $preset3cohort->id]) + ); + } }