From 33022ee1d5a9279b91ffeb6ce017eef122436b5b Mon Sep 17 00:00:00 2001 From: Jake Dallimore Date: Wed, 14 Nov 2018 13:58:18 +0800 Subject: [PATCH] MDL-63913 core_message: add method to get unread conversation counts --- message/classes/api.php | 53 ++++++++++++++++++++++++ message/tests/api_test.php | 82 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/message/classes/api.php b/message/classes/api.php index de7e08e9edd..6424ad08829 100644 --- a/message/classes/api.php +++ b/message/classes/api.php @@ -2923,4 +2923,57 @@ class api { return []; } + + /** + * Get the unread counts for all conversations for the user, sorted by type, and including favourites. + * + * @param int $userid the id of the user whose conversations we'll check. + * @return array the unread counts for each conversation, indexed by type. + */ + public static function get_unread_conversation_counts(int $userid) : array { + global $DB; + + // Get all conversations the user is in, and check unread. + $unreadcountssql = 'SELECT conv.id, conv.type, indcounts.unreadcount + FROM {message_conversations} conv + INNER JOIN ( + SELECT m.conversationid, count(m.id) as unreadcount + FROM {messages} m + INNER JOIN {message_conversations} mc + ON mc.id = m.conversationid + INNER JOIN {message_conversation_members} mcm + ON m.conversationid = mcm.conversationid + LEFT JOIN {message_user_actions} mua + ON (mua.messageid = m.id AND mua.userid = ? AND + (mua.action = ? OR mua.action = ?)) + WHERE mcm.userid = ? + AND m.useridfrom != ? + AND mua.id is NULL + GROUP BY m.conversationid + ) indcounts + ON indcounts.conversationid = conv.id + WHERE conv.enabled = 1'; + + $unreadcounts = $DB->get_records_sql($unreadcountssql, [$userid, self::MESSAGE_ACTION_READ, self::MESSAGE_ACTION_DELETED, + $userid, $userid]); + + // Get favourites, so we can track these separately. + $service = \core_favourites\service_factory::get_service_for_user_context(\context_user::instance($userid)); + $favouriteconversations = $service->find_favourites_by_type('core_message', 'message_conversations'); + $favouriteconvids = array_flip(array_column($favouriteconversations, 'itemid')); + + // Assemble the return array. + $counts = ['favourites' => 0, 'types' => [ + self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, + self::MESSAGE_CONVERSATION_TYPE_GROUP => 0 + ]]; + foreach ($unreadcounts as $convid => $info) { + $counts['types'][$info->type]++; + if (isset($favouriteconvids[$convid])) { + $counts['favourites']++; + } + } + + return $counts; + } } diff --git a/message/tests/api_test.php b/message/tests/api_test.php index 69841aff04f..f21039c65b3 100644 --- a/message/tests/api_test.php +++ b/message/tests/api_test.php @@ -5865,6 +5865,88 @@ class core_message_api_testcase extends core_message_messagelib_testcase { $this->assertEquals(2, \core_message\api::count_contacts($user1->id)); } + /** + * Test verifying the correctness of unread counts returned. + */ + public function test_get_unread_conversations_count() { + // Get a bunch of conversations, some group, some individual and in different states. + list($user1, $user2, $user3, $user4, $ic1, $ic2, $ic3, + $gc1, $gc2, $gc3, $gc4, $gc5, $gc6) = $this->create_conversation_test_data(); + + // Mark a couple as favourites. + \core_message\api::set_favourite_conversation($ic1->id, $user1->id); + \core_message\api::set_favourite_conversation($gc2->id, $user1->id); + + $counts = \core_message\api::get_unread_conversation_counts($user1->id); + $this->assertEquals(2, $counts['favourites']); + $this->assertEquals(2, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); + $this->assertEquals(2, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); + + \core_message\api::mark_all_messages_as_read($user1->id, $ic1->id); + + // Mark a conversation as read and confirm it's not included in the unread counts for its respective type. + $counts = \core_message\api::get_unread_conversation_counts($user1->id); + $this->assertEquals(1, $counts['favourites']); + $this->assertEquals(1, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); + $this->assertEquals(2, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); + } + + /** + * Test verifying the unread counts are 0 if no conversations exist. + */ + public function test_get_unread_conversations_count_no_conversations() { + $user1 = self::getDataGenerator()->create_user(); + $counts = \core_message\api::get_unread_conversation_counts($user1->id); + $this->assertEquals(0, $counts['favourites']); + $this->assertEquals(0, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL]); + $this->assertEquals(0, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); + } + + /** + * Test verifying that those linked conversations which have been disabled are excluded from unread counts. + */ + public function test_get_unread_conversations_count_disabled_conversations() { + global $DB; + + // Create some users. + $user1 = self::getDataGenerator()->create_user(); + $user2 = self::getDataGenerator()->create_user(); + $user3 = self::getDataGenerator()->create_user(); + + $course1 = $this->getDataGenerator()->create_course(); + + // Create a group with a linked conversation and a valid image. + $this->setAdminUser(); + $this->getDataGenerator()->enrol_user($user1->id, $course1->id); + $this->getDataGenerator()->enrol_user($user2->id, $course1->id); + $this->getDataGenerator()->enrol_user($user3->id, $course1->id); + $group1 = $this->getDataGenerator()->create_group([ + 'courseid' => $course1->id, + 'enablemessaging' => 1, + ]); + + // Add users to group1. + $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)); + $this->getDataGenerator()->create_group_member(array('groupid' => $group1->id, 'userid' => $user2->id)); + + $conversations = \core_message\api::get_conversations($user1->id); + $convid = $conversations[0]->id; + + // Send a message to the group conversation as user 2. + testhelper::send_fake_message_to_conversation($user2, $convid, 'Hello world!'); + + // Verify the unread count is 1. + $counts = \core_message\api::get_unread_conversation_counts($user1->id); + $this->assertEquals(1, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); + + // Now, disabled the linked conversation. + $DB->set_field('message_conversations', 'enabled', false, ['id' => $convid]); + + // Verify the unread count is no longer 1 as the conversation has been excluded. + $counts = \core_message\api::get_unread_conversation_counts($user1->id); + $this->assertEquals(0, $counts['types'][\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP]); + } + /** * Comparison function for sorting contacts. *