From 6399c7ef144bc7e480bc7539fb7d6dbf9c0e4ec2 Mon Sep 17 00:00:00 2001 From: Ryan Wyllie Date: Tue, 16 Oct 2018 11:44:55 +0800 Subject: [PATCH] MDL-63303 message: add count_conversations to api --- message/classes/api.php | 78 ++++++++++++ message/tests/api_test.php | 235 +++++++++++++++++++++++++++++++++++++ 2 files changed, 313 insertions(+) diff --git a/message/classes/api.php b/message/classes/api.php index 9788b21ced2..650d3e51975 100644 --- a/message/classes/api.php +++ b/message/classes/api.php @@ -1297,6 +1297,84 @@ class api { return false; } + /** + * Returns the count of conversations (collection of messages from a single user) for + * the given user. + * + * @param \stdClass $user The user who's conversations should be counted + * @param int $type The conversation type + * @param bool $excludefavourites Exclude favourite conversations + * @return int the count of the user's unread conversations + */ + public static function count_conversations($user, int $type = null, bool $excludefavourites = false) { + global $DB; + + $params = []; + $favouritessql = ''; + + if ($excludefavourites) { + $favouritessql = "AND m.conversationid NOT IN ( + SELECT itemid + FROM {favourite} + WHERE component = 'core_message' + AND itemtype = 'message_conversations' + AND userid = ? + )"; + $params[] = $user->id; + } + + switch($type) { + case null: + $params = array_merge([$user->id, self::MESSAGE_ACTION_DELETED, $user->id], $params); + $sql = "SELECT COUNT(DISTINCT(m.conversationid)) + FROM {messages} m + LEFT JOIN {message_conversations} c + ON m.conversationid = c.id + LEFT JOIN {message_user_actions} ma + ON ma.messageid = m.id + LEFT JOIN {message_conversation_members} mcm + ON m.conversationid = mcm.conversationid + WHERE mcm.userid = ? + AND ( + c.type != " . self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL . " + OR + ( + (ma.action IS NULL OR ma.action != ? OR ma.userid != ?) + AND c.type = " . self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL . " + ) + ) + ${favouritessql}"; + break; + case self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL: + $params = array_merge([self::MESSAGE_ACTION_DELETED, $user->id, $user->id], $params); + $sql = "SELECT COUNT(DISTINCT(m.conversationid)) + FROM {messages} m + LEFT JOIN {message_conversations} c + ON m.conversationid = c.id + LEFT JOIN {message_user_actions} ma + ON ma.messageid = m.id + LEFT JOIN {message_conversation_members} mcm + ON m.conversationid = mcm.conversationid + WHERE (ma.action IS NULL OR ma.action != ? OR ma.userid != ?) + AND mcm.userid = ? + AND c.type = " . self::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL . " + ${favouritessql}"; + break; + default: + $params = array_merge([$user->id, $type], $params); + $sql = "SELECT COUNT(m.conversationid) + FROM {message_conversation_members} m + LEFT JOIN {message_conversations} c + ON m.conversationid = c.id + WHERE m.userid = ? + AND c.type = ? + ${favouritessql}"; + + } + + return $DB->count_records_sql($sql, $params); + } + /** * Marks all messages being sent to a user in a particular conversation. * diff --git a/message/tests/api_test.php b/message/tests/api_test.php index 61fe9b04cba..6efdb1b63c3 100644 --- a/message/tests/api_test.php +++ b/message/tests/api_test.php @@ -5598,6 +5598,241 @@ class core_message_api_testcase extends core_message_messagelib_testcase { \core_message\api::send_message_to_conversation($user2->id, $ic1->id, 'test', FORMAT_MOODLE); } + /** + * Data provider for test_count_conversations(). + */ + public function test_count_conversations_test_cases() { + $typeindividual = \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL; + $typegroup = \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP; + list($user1, $user2, $user3, $user4, $user5) = [0, 1, 2, 3, 4]; + $conversations = [ + [ + 'type' => $typeindividual, + 'users' => [$user1, $user2], + 'messages' => [$user1, $user2], + 'favourites' => [$user1] + ], + [ + 'type' => $typeindividual, + 'users' => [$user1, $user3], + 'messages' => [$user1, $user1], + 'favourites' => [] + ], + [ + 'type' => $typegroup, + 'users' => [$user1, $user2, $user3, $user4], + 'messages' => [$user1, $user2, $user3, $user4], + 'favourites' => [] + ], + ]; + + return [ + 'No conversations' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user5], + 'expected' => 0 + ], + 'No individual conversations' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user4, $typeindividual], + 'expected' => 0 + ], + 'No individual conversations, 1 group conversation' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user4], + 'expected' => 1 + ], + '1 - Multiple individual conversations, 1 group conversation' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user1, $typegroup], + 'expected' => 1 + ], + '2 - Multiple individual conversations, 1 group conversation' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user2, $typegroup], + 'expected' => 1 + ], + '3 - Multiple individual conversations, 1 group conversation' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user3, $typegroup], + 'expected' => 1 + ], + '4 - Multiple individual conversations, 1 group conversation' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user4, $typegroup], + 'expected' => 1 + ], + 'Individual exclude favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user1, $typeindividual, true], + 'expected' => 1 + ], + 'Individual include favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user1, $typeindividual, false], + 'expected' => 2 + ], + 'All exclude favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user1, null, true], + 'expected' => 2 + ], + 'All include favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => null, + 'delete' => [], + 'arguments' => [$user1, null, false], + 'expected' => 3 + ], + 'Delete single message individual' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [1], + 'arguments' => [$user1, $typeindividual], + 'expected' => 2 + ], + 'Delete single message all' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [1], + 'arguments' => [$user1, null], + 'expected' => 3 + ], + 'Delete all message individual conversation include favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [2, 3], + 'arguments' => [$user1, $typeindividual, false], + 'expected' => 1 + ], + 'Delete all message individual conversation exclude favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [2, 3], + 'arguments' => [$user1, $typeindividual, true], + 'expected' => 0 + ], + 'Delete all message individual conversation include favourites diff user' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [2, 3], + 'arguments' => [$user2, $typeindividual, false], + 'expected' => 1 + ], + 'Delete all message individual conversation exclude favourites diff user' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [2, 3], + 'arguments' => [$user2, $typeindividual, true], + 'expected' => 1 + ], + 'Delete all message group conversation include favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [4, 5, 6, 7], + 'arguments' => [$user1, $typegroup, false], + 'expected' => 1 + ], + 'Delete all message group conversation include favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [4, 5, 6, 7], + 'arguments' => [$user1, null, false], + 'expected' => 3 + ], + 'Delete all message group conversation exclude favourites' => [ + 'conversationConfigs' => $conversations, + 'deleteuser' => $user1, + 'delete' => [4, 5, 6, 7], + 'arguments' => [$user1, null, true], + 'expected' => 2 + ] + ]; + } + + /** + * Test the count_conversations() function. + * + * @dataProvider test_count_conversations_test_cases() + * @param array $conversationconfigs Conversations to create + * @param int $deleteuser The user who is deleting the messages + * @param array $delete The list of messages to delete (by index) + * @param array $arguments Arguments for the count conversations function + * @param int $expected The expected result + */ + public function test_count_conversations( + $conversationconfigs, + $deleteuser, + $delete, + $arguments, + $expected + ) { + $generator = $this->getDataGenerator(); + $users = [ + $generator->create_user(), + $generator->create_user(), + $generator->create_user(), + $generator->create_user(), + $generator->create_user() + ]; + + $user = $users[$arguments[0]]; + $deleteuser = !is_null($deleteuser) ? $users[$deleteuser] : null; + $arguments[0] = $user; + $systemcontext = \context_system::instance(); + $conversations = []; + $messageids = []; + + foreach ($conversationconfigs as $config) { + $conversation = \core_message\api::create_conversation( + $config['type'], + array_map(function($userindex) use ($users) { + return $users[$userindex]->id; + }, $config['users']) + ); + + foreach ($config['messages'] as $userfromindex) { + $userfrom = $users[$userfromindex]; + $messageids[] = testhelper::send_fake_message_to_conversation($userfrom, $conversation->id); + } + + foreach ($config['favourites'] as $userfromindex) { + $userfrom = $users[$userfromindex]; + $usercontext = \context_user::instance($userfrom->id); + $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); + $ufservice->create_favourite('core_message', 'message_conversations', $conversation->id, $systemcontext); + } + + $conversations[] = $conversation; + } + + foreach ($delete as $messageindex) { + \core_message\api::delete_message($deleteuser->id, $messageids[$messageindex]); + } + + $this->assertEquals($expected, \core_message\api::count_conversations(...$arguments)); + } + /** * Comparison function for sorting contacts. *