diff --git a/classes/helper.php b/classes/helper.php index 6d599b6..6b03293 100644 --- a/classes/helper.php +++ b/classes/helper.php @@ -144,6 +144,61 @@ public static function remove_item(int $itemid, string $itemtype, string $itemna } } + /** + * Rename item. + * + * @param int $itemid Item ID. + * @param string $itemtype Item type (tag, course, category). + * @param string $newname Item new name. + * @return void + */ + public static function rename_item(int $itemid, string $itemtype, string $newname): void { + global $DB; + + // Get cohort to figure out an old name. + $cohort = helper::get_cohort_by_item($itemid, $itemtype); + + if ($cohort && $cohort->name != $newname) { + $oldname = $cohort->name; + + // Update cohort with a new name. + $cohort->name = $newname; + unset($cohort->customfields); + cohort_update_cohort($cohort); + + // Update rule with a new name. + $rule = rule::get_record(['cohortid' => $cohort->id]); + if ($rule) { + $rule->set('name', $newname); + $rule->save(); + } + + // 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) { + $fieldselect = $DB->sql_like('data', ':value', false, false); + $value = $DB->sql_like_escape($oldname); + $params['value'] = "%$value%"; + $params['fieldid'] = $field->id; + + $where = "$fieldselect AND fieldid = :fieldid"; + $usersdata = $DB->get_records_select('user_info_data', $where, $params); + + foreach ($usersdata as $userdata) { + $data = explode(', ', $userdata->data); + $key = array_search($oldname, $data); + $data[$key] = $newname; + $userdata->data = implode(', ', $data); + $DB->update_record('user_info_data', $userdata); + } + } + } + } + /** * Get cohort by provided item type and item id. * @@ -295,6 +350,35 @@ public static function delete_profile_field_item(string $shortname, string $item } } + /** + * Delete a given item from profile field. + * + * @param string $shortname Field short name. + * @param string $oldname Old name of the item + * @param string $newname New name of the item. + * + * @return void + */ + public static function update_profile_field_item(string $shortname, string $oldname, string $newname): void { + global $DB; + + $field = $DB->get_record('user_info_field', ['shortname' => $shortname]); + if ($field) { + $fielddata = []; + if (!empty($field->param1)) { + $fielddata = explode("\n", $field->param1); + } + + if (in_array($oldname, $fielddata)) { + $key = array_search($oldname, $fielddata); + $fielddata[$key] = $newname; + sort($fielddata); + $field->param1 = implode("\n", $fielddata); + $DB->update_record('user_info_field', $field); + } + } + } + /** * Add cohort. * diff --git a/classes/observer.php b/classes/observer.php index 61c332f..b6a10e4 100644 --- a/classes/observer.php +++ b/classes/observer.php @@ -23,8 +23,8 @@ use core\event\tag_added; use core\event\tag_removed; use core\event\tag_deleted; +use core\event\tag_updated; use tool_dynamic_cohorts\rule; -use tool_dynamic_cohorts\rule_manager; /** * Event observer class. @@ -82,6 +82,17 @@ public static function tag_deleted(tag_deleted $event): void { helper::remove_item($tagid, helper::ITEM_TYPE_TAG, $tagname); } + /** + * Process tag_deleted event. + * + * @param tag_updated $event The event. + */ + public static function tag_updated(tag_updated $event): void { + $tagid = $event->objectid; + $tagnewname = $event->other['rawname']; + helper::rename_item($tagid, helper::ITEM_TYPE_TAG, $tagnewname); + } + /** * Process course_created event. * diff --git a/db/events.php b/db/events.php index 436ff20..9e6f3b7 100644 --- a/db/events.php +++ b/db/events.php @@ -37,6 +37,10 @@ 'eventname' => '\core\event\tag_deleted', 'callback' => '\tool_enrolprofile\observer::tag_deleted', ], + [ + 'eventname' => '\core\event\tag_updated', + 'callback' => '\tool_enrolprofile\observer::tag_updated', + ], [ 'eventname' => '\core\event\course_created', 'callback' => '\tool_enrolprofile\observer::course_created', diff --git a/tests/observer_test.php b/tests/observer_test.php index a9cf281..d9011a7 100644 --- a/tests/observer_test.php +++ b/tests/observer_test.php @@ -20,6 +20,7 @@ use core_customfield\field_controller; use core_tag_tag; use context_course; +use core_user; /** * Unit tests for observer class. @@ -174,6 +175,134 @@ public function test_tag_added(): void { $this->assertNotEmpty($enrol); } + /** + * Check logic when updating a tag. + */ + public function test_tag_updated(): void { + global $DB; + + $course = $this->getDataGenerator()->create_course(); + $profilefield = 'profile_field_' . helper::ITEM_TYPE_TAG; + $tagname = 'A tag'; + + core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), [ + $tagname, + 'Not tag', + 'Another tag', + ]); + + $tag = $DB->get_record('tag', ['rawname' => $tagname]); + $this->assertNotEmpty($tag); + + $cohort = $DB->get_record('cohort', ['name' => $tagname]); + $this->assertNotEmpty($cohort); + + $cohort = cohort_get_cohort($cohort->id, context_course::instance($course->id), true); + foreach ($cohort->customfields as $customfield) { + if ($customfield->get_field()->get('shortname') == helper::COHORT_FIELD_ID) { + $this->assertSame($tag->id, $customfield->export_value()); + } + if ($customfield->get_field()->get('shortname') == helper::COHORT_FIELD_TYPE) { + $this->assertSame(helper::ITEM_TYPE_TAG, $customfield->export_value()); + } + } + + $profilefielddata = $DB->get_field('user_info_field', 'param1', ['id' => $this->tagprofilefield->id]); + $this->assertNotEmpty($profilefielddata); + $this->assertTrue(in_array($tagname, explode("\n", $profilefielddata))); + + $rule = $DB->get_record('tool_dynamic_cohorts', ['name' => $tagname]); + $this->assertNotEmpty($rule); + $this->assertEquals($cohort->id, $rule->cohortid); + + $user1 = $this->getDataGenerator()->create_user(); + profile_save_data((object)[ + 'id' => $user1->id, + $profilefield => [ + 'Not tag', + $tagname, + 'Another tag', + ] + ]); + + $user2 = $this->getDataGenerator()->create_user(); + profile_save_data((object)[ + 'id' => $user2->id, + $profilefield => [ + $tagname, + 'Another tag', + ] + ]); + + profile_load_data($user1); + $this->assertSame([ + 'Not tag', + $tagname, + 'Another tag', + ], $user1->$profilefield + ); + profile_load_data($user2); + $this->assertSame([ + $tagname, + 'Another tag', + ], $user2->$profilefield + ); + + // Update name of the tag. + $newtagname = 'A new tag name'; + core_tag_tag::get($tag->id, '*')->update(array('rawname' => $newtagname)); + + $tag = $DB->get_record('tag', ['rawname' => $tagname]); + $this->assertEmpty($tag); + + $tag = $DB->get_record('tag', ['rawname' => $newtagname]); + $this->assertNotEmpty($tag); + + $cohort = $DB->get_record('cohort', ['name' => $tagname]); + $this->assertEmpty($cohort); + + $cohort = $DB->get_record('cohort', ['name' => $newtagname]); + $this->assertNotEmpty($cohort); + + $cohort = cohort_get_cohort($cohort->id, context_course::instance($course->id), true); + foreach ($cohort->customfields as $customfield) { + if ($customfield->get_field()->get('shortname') == helper::COHORT_FIELD_ID) { + $this->assertSame($tag->id, $customfield->export_value()); + } + if ($customfield->get_field()->get('shortname') == helper::COHORT_FIELD_TYPE) { + $this->assertSame(helper::ITEM_TYPE_TAG, $customfield->export_value()); + } + } + + $profilefielddata = $DB->get_field('user_info_field', 'param1', ['id' => $this->tagprofilefield->id]); + $this->assertNotEmpty($profilefielddata); + $this->assertFalse(in_array($tagname, explode("\n", $profilefielddata))); + $this->assertTrue(in_array($newtagname, explode("\n", $profilefielddata))); + + $rule = $DB->get_record('tool_dynamic_cohorts', ['name' => $tagname]); + $this->assertEmpty($rule); + + $rule = $DB->get_record('tool_dynamic_cohorts', ['name' => $newtagname]); + $this->assertNotEmpty($rule); + $this->assertEquals($cohort->id, $rule->cohortid); + + profile_load_data($user1); + $this->assertSame([ + 'Not tag', + $newtagname, + 'Another tag', + ], $user1->$profilefield + ); + profile_load_data($user2); + $this->assertSame([ + $newtagname, + 'Another tag', + ], $user2->$profilefield + ); + + } + + /** * Check logic when removing a tag. */