MDL-63725 core_message: added get_conversation_members web service
authorMark Nelson <markn@moodle.com>
Thu, 25 Oct 2018 23:52:22 +0000 (07:52 +0800)
committerMark Nelson <markn@moodle.com>
Thu, 1 Nov 2018 03:18:20 +0000 (11:18 +0800)
lib/db/services.php
message/externallib.php
message/tests/externallib_test.php
version.php

index 1c4a37f..0007fe1 100644 (file)
@@ -1045,6 +1045,15 @@ $functions = array(
         'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
         'ajax' => true,
     ),
+    'core_message_get_conversation_members' => array(
+        'classname' => 'core_message_external',
+        'methodname' => 'get_conversation_members',
+        'classpath' => 'message/externallib.php',
+        'description' => 'Retrieve a list of members in a conversation',
+        'type' => 'read',
+        'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+        'ajax' => true,
+    ),
     'core_message_get_unread_conversations_count' => array(
         'classname' => 'core_message_external',
         'methodname' => 'get_unread_conversations_count',
index 75c19ec..dc95f88 100644 (file)
@@ -667,6 +667,76 @@ class core_message_external extends external_api {
         );
     }
 
+    /**
+     * Returns get conversation members parameters description.
+     *
+     * @return external_function_parameters
+     */
+    public static function get_conversation_members_parameters() {
+        return new external_function_parameters(
+            [
+                'userid' => new external_value(PARAM_INT, 'The id of the user we are performing this action on behalf of'),
+                'conversationid' => new external_value(PARAM_INT, 'The id of the conversation'),
+                'includecontactrequests' => new external_value(PARAM_BOOL, 'Do we want to include contact requests?',
+                    VALUE_DEFAULT, false),
+                'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
+                'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
+            ]
+        );
+    }
+
+    /**
+     * Returns a list of conversation members.
+     *
+     * @param int $userid The user we are returning the conversation members for, used by helper::get_member_info.
+     * @param int $conversationid The id of the conversation
+     * @param bool $includecontactrequests Do we want to include contact requests with this data?
+     * @param int $limitfrom
+     * @param int $limitnum
+     * @return array
+     */
+    public static function get_conversation_members(int $userid, int $conversationid, bool $includecontactrequests = false,
+                                                    int $limitfrom = 0, int $limitnum = 0) {
+        global $CFG, $USER;
+
+        // Check if messaging is enabled.
+        if (empty($CFG->messaging)) {
+            throw new moodle_exception('disabled', 'message');
+        }
+
+        // Validate context.
+        $context = context_system::instance();
+        self::validate_context($context);
+
+        $capability = 'moodle/site:manageallmessaging';
+        if (($USER->id != $userid) && !has_capability($capability, $context)) {
+            throw new required_capability_exception($context, $capability, 'nopermissions', '');
+        }
+
+        $params = [
+            'userid' => $userid,
+            'conversationid' => $conversationid,
+            'includecontactrequests' => $includecontactrequests,
+            'limitfrom' => $limitfrom,
+            'limitnum' => $limitnum
+        ];
+        self::validate_parameters(self::get_conversation_members_parameters(), $params);
+
+        return \core_message\api::get_conversation_members($userid, $conversationid, $includecontactrequests,
+            $limitfrom, $limitnum);
+    }
+
+    /**
+     * Returns the get conversation members return description.
+     *
+     * @return external_description
+     */
+    public static function get_conversation_members_returns() {
+        return new external_multiple_structure(
+            self::get_conversation_member_structure(true)
+        );
+    }
+
     /**
      * Creates a contact request parameters description.
      *
@@ -871,21 +941,37 @@ class core_message_external extends external_api {
     /**
      * Return the structure of a conversation member.
      *
+     * @param bool $includecontactrequests Are we including contact requests?
      * @return external_single_structure
      * @since Moodle 3.6
      */
-    private static function get_conversation_member_structure() {
+    private static function get_conversation_member_structure(bool $includecontactrequests = false) {
+        $result = [
+            'id' => new external_value(PARAM_INT, 'The user id'),
+            'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
+            'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
+            'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
+            'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
+            'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
+            'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
+            'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
+        ];
+
+        if ($includecontactrequests) {
+            $result['contactrequests'] = new external_multiple_structure(
+                new external_single_structure(
+                    [
+                        'id' => new external_value(PARAM_INT, 'The id of the message'),
+                        'userid' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
+                        'requesteduserid' => new external_value(PARAM_RAW, 'The text of the message'),
+                        'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
+                    ]
+                ), 'The contact requests', VALUE_OPTIONAL
+            );
+        }
+
         return new external_single_structure(
-            array(
-                'id' => new external_value(PARAM_INT, 'The user id'),
-                'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
-                'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
-                'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
-                'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
-                'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
-                'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
-                'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
-            )
+            $result
         );
     }
 
index f406dbd..1282737 100644 (file)
@@ -4339,4 +4339,215 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $this->expectException(\moodle_exception::class);
         $result = core_message_external::unset_favourite_conversations($user1->id, [0]);
     }
+
+    /**
+     * Test returning members in a conversation with no contact requests.
+     */
+    public function test_get_conversation_members_messaging_disabled() {
+        global $CFG;
+
+        $this->resetAfterTest();
+
+        $CFG->messaging = 0;
+
+        $this->expectException('moodle_exception');
+        core_message_external::get_conversation_members(1, 2);
+    }
+
+    /**
+     * Test returning members in a conversation with no contact requests.
+     */
+    public function test_get_conversation_members_wrong_user() {
+        $this->resetAfterTest();
+
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        $this->setUser($user2);
+
+        $this->expectException('moodle_exception');
+        core_message_external::get_conversation_members($user1->id, 2);
+    }
+
+    /**
+     * Test returning members in a conversation with no contact requests.
+     */
+    public function test_get_conversation_members() {
+        $this->resetAfterTest();
+
+        $lastaccess = new stdClass();
+        $lastaccess->lastaccess = time();
+
+        $user1 = self::getDataGenerator()->create_user($lastaccess);
+        $user2 = self::getDataGenerator()->create_user();
+        $user3 = self::getDataGenerator()->create_user();
+
+        // This user will not be in the conversation, but a contact request will exist for them.
+        $user4 = self::getDataGenerator()->create_user();
+
+        // Add some contact requests.
+        \core_message\api::create_contact_request($user1->id, $user3->id);
+        \core_message\api::create_contact_request($user1->id, $user4->id);
+        \core_message\api::create_contact_request($user2->id, $user3->id);
+
+        // User 1 and 2 are already contacts.
+        \core_message\api::add_contact($user1->id, $user2->id);
+
+        // User 1 has blocked user 3.
+        \core_message\api::block_user($user1->id, $user3->id);
+
+        $conversation = \core_message\api::create_conversation(
+            \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
+            [
+                $user1->id,
+                $user2->id,
+                $user3->id
+            ]
+        );
+        $conversationid = $conversation->id;
+
+        $this->setAdminUser();
+
+        $members = core_message_external::get_conversation_members($user1->id, $conversationid, false);
+        external_api::clean_returnvalue(core_message_external::get_conversation_members_returns(), $members);
+
+        // Sort them by id.
+        ksort($members);
+        $this->assertCount(3, $members);
+        $member1 = array_shift($members);
+        $member2 = array_shift($members);
+        $member3 = array_shift($members);
+
+        // Confirm the standard fields are OK.
+        $this->assertEquals($user1->id, $member1->id);
+        $this->assertEquals(fullname($user1), $member1->fullname);
+        $this->assertEquals(true, $member1->isonline);
+        $this->assertEquals(true, $member1->showonlinestatus);
+        $this->assertEquals(false, $member1->iscontact);
+        $this->assertEquals(false, $member1->isblocked);
+        $this->assertObjectNotHasAttribute('contactrequests', $member1);
+
+        $this->assertEquals($user2->id, $member2->id);
+        $this->assertEquals(fullname($user2), $member2->fullname);
+        $this->assertEquals(false, $member2->isonline);
+        $this->assertEquals(true, $member2->showonlinestatus);
+        $this->assertEquals(true, $member2->iscontact);
+        $this->assertEquals(false, $member2->isblocked);
+        $this->assertObjectNotHasAttribute('contactrequests', $member2);
+
+        $this->assertEquals($user3->id, $member3->id);
+        $this->assertEquals(fullname($user3), $member3->fullname);
+        $this->assertEquals(false, $member3->isonline);
+        $this->assertEquals(true, $member3->showonlinestatus);
+        $this->assertEquals(false, $member3->iscontact);
+        $this->assertEquals(true, $member3->isblocked);
+        $this->assertObjectNotHasAttribute('contactrequests', $member3);
+    }
+
+    /**
+     * Test returning members in a conversation with contact requests.
+     */
+    public function test_get_conversation_members_with_contact_requests() {
+        $this->resetAfterTest();
+
+        $lastaccess = new stdClass();
+        $lastaccess->lastaccess = time();
+
+        $user1 = self::getDataGenerator()->create_user($lastaccess);
+        $user2 = self::getDataGenerator()->create_user();
+        $user3 = self::getDataGenerator()->create_user();
+
+        // This user will not be in the conversation, but a contact request will exist for them.
+        $user4 = self::getDataGenerator()->create_user();
+
+        // Add some contact requests.
+        \core_message\api::create_contact_request($user1->id, $user2->id);
+        \core_message\api::create_contact_request($user1->id, $user3->id);
+        \core_message\api::create_contact_request($user1->id, $user4->id);
+        \core_message\api::create_contact_request($user2->id, $user3->id);
+
+        // User 1 and 2 are already contacts.
+        \core_message\api::add_contact($user1->id, $user2->id);
+        // User 1 has blocked user 3.
+        \core_message\api::block_user($user1->id, $user3->id);
+
+        $conversation = \core_message\api::create_conversation(
+            \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
+            [
+                $user1->id,
+                $user2->id,
+                $user3->id
+            ]
+        );
+        $conversationid = $conversation->id;
+
+        $this->setAdminUser();
+
+        $members = core_message_external::get_conversation_members($user1->id, $conversationid, true);
+        external_api::clean_returnvalue(core_message_external::get_conversation_members_returns(), $members);
+
+        // Sort them by id.
+        ksort($members);
+        $this->assertCount(3, $members);
+        $member1 = array_shift($members);
+        $member2 = array_shift($members);
+        $member3 = array_shift($members);
+
+        // Confirm the standard fields are OK.
+        $this->assertEquals($user1->id, $member1->id);
+        $this->assertEquals(fullname($user1), $member1->fullname);
+        $this->assertEquals(true, $member1->isonline);
+        $this->assertEquals(true, $member1->showonlinestatus);
+        $this->assertEquals(false, $member1->iscontact);
+        $this->assertEquals(false, $member1->isblocked);
+        $this->assertCount(3, $member1->contactrequests);
+
+        $this->assertEquals($user2->id, $member2->id);
+        $this->assertEquals(fullname($user2), $member2->fullname);
+        $this->assertEquals(false, $member2->isonline);
+        $this->assertEquals(true, $member2->showonlinestatus);
+        $this->assertEquals(true, $member2->iscontact);
+        $this->assertEquals(false, $member2->isblocked);
+        $this->assertCount(2, $member2->contactrequests);
+
+        $this->assertEquals($user3->id, $member3->id);
+        $this->assertEquals(fullname($user3), $member3->fullname);
+        $this->assertEquals(false, $member3->isonline);
+        $this->assertEquals(true, $member3->showonlinestatus);
+        $this->assertEquals(false, $member3->iscontact);
+        $this->assertEquals(true, $member3->isblocked);
+        $this->assertCount(2, $member3->contactrequests);
+
+        // Confirm the contact requests are OK.
+        $request1 = array_shift($member1->contactrequests);
+        $request2 = array_shift($member1->contactrequests);
+        $request3 = array_shift($member1->contactrequests);
+
+        $this->assertEquals($user1->id, $request1->userid);
+        $this->assertEquals($user2->id, $request1->requesteduserid);
+
+        $this->assertEquals($user1->id, $request2->userid);
+        $this->assertEquals($user3->id, $request2->requesteduserid);
+
+        $this->assertEquals($user1->id, $request3->userid);
+        $this->assertEquals($user4->id, $request3->requesteduserid);
+
+        $request1 = array_shift($member2->contactrequests);
+        $request2 = array_shift($member2->contactrequests);
+
+        $this->assertEquals($user1->id, $request1->userid);
+        $this->assertEquals($user2->id, $request1->requesteduserid);
+
+        $this->assertEquals($user2->id, $request2->userid);
+        $this->assertEquals($user3->id, $request2->requesteduserid);
+
+        $request1 = array_shift($member3->contactrequests);
+        $request2 = array_shift($member3->contactrequests);
+
+        $this->assertEquals($user1->id, $request1->userid);
+        $this->assertEquals($user3->id, $request1->requesteduserid);
+
+        $this->assertEquals($user2->id, $request2->userid);
+        $this->assertEquals($user3->id, $request2->requesteduserid);
+    }
 }
index 810a9f4..61e0e2b 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2018103100.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2018110100.00;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.