From 3e47253787f24c486cb372ea2f091586e9cb6590 Mon Sep 17 00:00:00 2001 From: Safat Date: Fri, 4 Aug 2023 16:47:49 +1000 Subject: [PATCH] MDL-78129 core_communication: Add update membership api --- communication/classes/api.php | 29 +++++++++ communication/classes/processor.php | 24 +++++++ communication/classes/room_user_provider.php | 7 ++ .../classes/task/remove_members_from_room.php | 2 +- .../task/update_room_membership_task.php | 64 +++++++++++++++++++ communication/tests/api_test.php | 38 ++++++++++- communication/tests/processor_test.php | 40 ++++++++++++ lib/accesslib.php | 22 +++++++ 8 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 communication/classes/task/update_room_membership_task.php diff --git a/communication/classes/api.php b/communication/classes/api.php index db3f454bec7..4d2fa922666 100644 --- a/communication/classes/api.php +++ b/communication/classes/api.php @@ -21,6 +21,7 @@ use core_communication\task\create_and_configure_room_task; use core_communication\task\delete_room_task; use core_communication\task\remove_members_from_room; use core_communication\task\update_room_task; +use core_communication\task\update_room_membership_task; use stdClass; /** @@ -531,6 +532,34 @@ class api { } } + /** + * Create a communication ad-hoc task for updating members operation and update the user mapping. + * + * This method will add a task to the queue to update the room users. + * + * @param array $userids The user ids to add to the room + * @param bool $queue Whether to queue the task or not + */ + public function update_room_membership(array $userids, bool $queue = true): void { + // No communication object? something not done right. + if (!$this->communication) { + return; + } + + // No userids? don't bother doing anything. + if (empty($userids)) { + return; + } + + $this->communication->reset_users_sync_flag($userids); + + if ($queue) { + update_room_membership_task::queue( + $this->communication + ); + } + } + /** * Create a communication ad-hoc task for remove members operation or action immediately. * diff --git a/communication/classes/processor.php b/communication/classes/processor.php index 82f40965302..bde03737975 100644 --- a/communication/classes/processor.php +++ b/communication/classes/processor.php @@ -171,6 +171,21 @@ class processor { ); } + /** + * Get all the user ids flagged as deleted. + * + * @return array + */ + public function get_all_delete_flagged_userids(): array { + global $DB; + return $DB->get_fieldset_select( + 'communication_user', + 'userid', + 'commid = ? AND deleted = ?', + [$this->instancedata->id, 1] + ); + } + /** * Create communication user record for mapping and sync. * @@ -400,6 +415,15 @@ class processor { /** * Get communication instance id. * + * @return int + */ + public function get_instance_id(): int { + return $this->instancedata->instanceid; + } + + /** + * Get communication instance component. + * * @return string */ public function get_component(): string { diff --git a/communication/classes/room_user_provider.php b/communication/classes/room_user_provider.php index f9a04e48a4b..f055c706365 100644 --- a/communication/classes/room_user_provider.php +++ b/communication/classes/room_user_provider.php @@ -31,6 +31,13 @@ interface room_user_provider { */ public function add_members_to_room(array $userids): void; + /** + * Update room membership for the communication room. + * + * @param array $userids The user ids to be updated + */ + public function update_room_membership(array $userids): void; + /** * Remove members from room. * diff --git a/communication/classes/task/remove_members_from_room.php b/communication/classes/task/remove_members_from_room.php index e681f949e01..72866b40e2e 100644 --- a/communication/classes/task/remove_members_from_room.php +++ b/communication/classes/task/remove_members_from_room.php @@ -40,7 +40,7 @@ class remove_members_from_room extends adhoc_task { return; } - $communication->get_room_user_provider()->remove_members_from_room($communication->get_instance_userids(true, true)); + $communication->get_room_user_provider()->remove_members_from_room($communication->get_all_delete_flagged_userids()); // Now remove any mapping for users who are not in the room. $communication->delete_instance_non_synced_user_mapping($communication->get_instance_userids(false, true)); diff --git a/communication/classes/task/update_room_membership_task.php b/communication/classes/task/update_room_membership_task.php new file mode 100644 index 00000000000..e65136d8e15 --- /dev/null +++ b/communication/classes/task/update_room_membership_task.php @@ -0,0 +1,64 @@ +. + +namespace core_communication\task; + +use core\task\adhoc_task; +use core_communication\processor; + +/** + * Class update_room_membership_task to add the task to update members for the room and execute the task to action the addition. + * + * @package core_communication + * @copyright 2023 Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class update_room_membership_task extends adhoc_task { + + public function execute() { + // Initialize the custom data operation to be used for the action. + $data = $this->get_custom_data(); + + // Call the communication api to action the operation. + $communication = processor::load_by_id($data->id); + + if ($communication === null) { + mtrace("Skipping room creation because the instance does not exist"); + return; + } + + $communication->get_room_user_provider()->update_room_membership($communication->get_instance_userids()); + } + + /** + * Queue the task for the next run. + * + * @param processor $communication The communication processor to perform the action on + */ + public static function queue( + processor $communication + ): void { + + // Add ad-hoc task to update the provider room. + $task = new self(); + $task->set_custom_data([ + 'id' => $communication->get_id() + ]); + + // Queue the task for the next run. + \core\task\manager::queue_adhoc_task($task); + } +} diff --git a/communication/tests/api_test.php b/communication/tests/api_test.php index ca1787a4b43..be95a54c164 100644 --- a/communication/tests/api_test.php +++ b/communication/tests/api_test.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/communication_test_helper_trait.php'); * @category test * @copyright 2023 Safat Shahin * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @covers \core_communication\api + * @coversDefaultClass \core_communication\api */ class api_test extends \advanced_testcase { @@ -251,9 +251,12 @@ class api_test extends \advanced_testcase { } /** - * Test the update_room_membership for adding adn removing members. + * Test the adding and removing of members from room. + * + * @covers ::add_members_to_room + * @covers ::remove_members_from_room */ - public function test_update_room_membership(): void { + public function test_adding_and_removing_of_room_membership(): void { $course = $this->get_course(); $userid = $this->get_user()->id; @@ -288,4 +291,33 @@ class api_test extends \advanced_testcase { $this->assertCount(count($plugins) + 1, $communicationproviders); $this->assertEquals(processor::PROVIDER_NONE, $defaulprovider); } + + /** + * Test the update of room membership with the change user role. + * + * @covers ::update_room_membership + */ + public function test_update_room_membership_on_user_role_change(): void { + global $DB; + + // Generate the data. + $user = $this->getDataGenerator()->create_user(); + $course = $this->get_course(); + $coursecontext = \context_course::instance($course->id); + $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); + $this->getDataGenerator()->enrol_user($user->id, $course->id); + + $adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\add_members_to_room_task'); + $this->assertCount(1, $adhoctask); + + $adhoctask = reset($adhoctask); + $this->assertInstanceOf('\\core_communication\\task\\add_members_to_room_task', $adhoctask); + + // Test the tasks added as the role is a teacher. + $adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\update_room_membership_task'); + $this->assertCount(1, $adhoctask); + + $adhoctask = reset($adhoctask); + $this->assertInstanceOf('\\core_communication\\task\\update_room_membership_task', $adhoctask); + } } diff --git a/communication/tests/processor_test.php b/communication/tests/processor_test.php index a8b58614f44..1a75530b96b 100644 --- a/communication/tests/processor_test.php +++ b/communication/tests/processor_test.php @@ -428,4 +428,44 @@ class processor_test extends \advanced_testcase { set_config('disabled', 1, $communicationprovider); $this->assertFalse(processor::is_provider_enabled($communicationprovider)); } + + /** + * Test delete flagged user id's return correct users. + * + * @covers ::get_all_delete_flagged_userids + */ + public function test_get_all_delete_flagged_userids(): void { + $this->resetAfterTest(); + + $course = $this->get_course('Sampleroom', 'none'); + $user1 = $this->getDataGenerator()->create_user()->id; + $user2 = $this->getDataGenerator()->create_user()->id; + + // Sample data. + $communicationroomname = 'Sampleroom'; + $selectedcommunication = 'communication_matrix'; + $component = 'core_course'; + $instancetype = 'coursecommunication'; + + // Load the communication api. + $communication = \core_communication\api::load_by_instance( + 'core_course', + 'coursecommunication', + $course->id + ); + $communication->create_and_configure_room($selectedcommunication, $communicationroomname); + $communication->add_members_to_room([$user1, $user2]); + + // Now remove user1 from the room. + $communication->remove_members_from_room([$user1]); + + // Test against the object. + $communicationprocessor = processor::load_by_instance( + $component, + $instancetype, + $course->id + ); + + $this->assertEquals([$user1], $communicationprocessor->get_all_delete_flagged_userids()); + } } diff --git a/lib/accesslib.php b/lib/accesslib.php index d5699be6290..f0a8375b330 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -1645,6 +1645,17 @@ function role_assign($roleid, $userid, $contextid, $component = '', $itemid = 0, core_course_category::role_assignment_changed($roleid, $context); + // Update the room membership and power levels when the user role changes. + if (\core_communication\api::is_available() && $coursecontext = $context->get_course_context(false)) { + $communication = \core_communication\api::load_by_instance( + 'core_course', + 'coursecommunication', + $coursecontext->instanceid, + ); + + $communication->update_room_membership([$userid]); + } + $event = \core\event\role_assigned::create(array( 'context' => $context, 'objectid' => $ra->roleid, @@ -1688,6 +1699,17 @@ function role_unassign($roleid, $userid, $contextid, $component = '', $itemid = } } + // Update the room membership and power levels when the user role changes. + if (\core_communication\api::is_available() && $coursecontext = $context->get_course_context(false)) { + $communication = \core_communication\api::load_by_instance( + 'core_course', + 'coursecommunication', + $coursecontext->instanceid, + ); + + $communication->update_room_membership([$userid]); + } + role_unassign_all(array('roleid'=>$roleid, 'userid'=>$userid, 'contextid'=>$contextid, 'component'=>$component, 'itemid'=>$itemid), false, false); }