2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * External message API
21 * @package core_message
23 * @copyright 2011 Jerome Mouneyrac
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
29 require_once("$CFG->libdir/externallib.php");
30 require_once($CFG->dirroot . "/message/lib.php");
33 * Message external functions
35 * @package core_message
37 * @copyright 2011 Jerome Mouneyrac
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 class core_message_external extends external_api {
43 * Returns description of method parameters
45 * @return external_function_parameters
48 public static function send_messages_to_conversation_parameters() {
49 return new external_function_parameters(
51 'conversationid' => new external_value(PARAM_INT, 'id of the conversation'),
52 'messages' => new external_multiple_structure(
53 new external_single_structure(
55 'text' => new external_value(PARAM_RAW, 'the text of the message'),
56 'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
65 * Send messages from the current USER to a conversation.
67 * This conversation may be any type of conversation, individual or group.
69 * @param int $conversationid the id of the conversation to which the messages will be sent.
70 * @param array $messages An array of message to send.
71 * @return array the array of messages which were sent (created).
74 public static function send_messages_to_conversation(int $conversationid, array $messages = []) {
77 // Check if messaging is enabled.
78 if (empty($CFG->messaging)) {
79 throw new moodle_exception('disabled', 'message');
82 // Ensure the current user is allowed to run this function.
83 $context = context_system::instance();
84 self::validate_context($context);
86 $params = self::validate_parameters(self::send_messages_to_conversation_parameters(), [
87 'conversationid' => $conversationid,
88 'messages' => $messages
92 foreach ($params['messages'] as $message) {
93 $messages[] = \core_message\api::send_message_to_conversation($USER->id, $params['conversationid'], $message['text'],
94 $message['textformat']);
101 * Returns description of method result value.
103 * @return external_description
106 public static function send_messages_to_conversation_returns() {
107 return new external_multiple_structure(
108 self::get_conversation_message_structure()
114 * Returns description of method parameters
116 * @return external_function_parameters
119 public static function send_instant_messages_parameters() {
120 return new external_function_parameters(
122 'messages' => new external_multiple_structure(
123 new external_single_structure(
125 'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
126 'text' => new external_value(PARAM_RAW, 'the text of the message'),
127 'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
128 'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own client id for the message. If this id is provided, the fail message id will be returned to you', VALUE_OPTIONAL),
137 * Send private messages from the current USER to other users
139 * @param array $messages An array of message to send.
143 public static function send_instant_messages($messages = array()) {
144 global $CFG, $USER, $DB;
146 // Check if messaging is enabled.
147 if (empty($CFG->messaging)) {
148 throw new moodle_exception('disabled', 'message');
151 // Ensure the current user is allowed to run this function
152 $context = context_system::instance();
153 self::validate_context($context);
154 require_capability('moodle/site:sendmessage', $context);
156 $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
158 //retrieve all tousers of the messages
159 $receivers = array();
160 foreach($params['messages'] as $message) {
161 $receivers[] = $message['touserid'];
163 list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers);
164 $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
166 $resultmessages = array();
167 foreach ($params['messages'] as $message) {
168 $resultmsg = array(); //the infos about the success of the operation
170 // We are going to do some checking.
171 // Code should match /messages/index.php checks.
174 // Check the user exists.
175 if (empty($tousers[$message['touserid']])) {
177 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
180 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
181 // Check if the recipient can be messaged by the sender.
182 if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
184 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
187 // Now we can send the message (at least try).
189 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
190 $success = message_post_message($USER, $tousers[$message['touserid']],
191 $message['text'], external_validate_format($message['textformat']));
194 // Build the resultmsg.
195 if (isset($message['clientmsgid'])) {
196 $resultmsg['clientmsgid'] = $message['clientmsgid'];
199 $resultmsg['msgid'] = $success;
201 // WARNINGS: for backward compatibility we return this errormessage.
202 // We should have thrown exceptions as these errors prevent results to be returned.
203 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
204 $resultmsg['msgid'] = -1;
205 $resultmsg['errormessage'] = $errormessage;
208 $resultmessages[] = $resultmsg;
211 return $resultmessages;
215 * Returns description of method result value
217 * @return external_description
220 public static function send_instant_messages_returns() {
221 return new external_multiple_structure(
222 new external_single_structure(
224 'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds: id of the created message if it succeeded, -1 when failed'),
225 'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
226 'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL)
233 * Create contacts parameters description.
235 * @deprecated since Moodle 3.6
236 * @return external_function_parameters
239 public static function create_contacts_parameters() {
240 return new external_function_parameters(
242 'userids' => new external_multiple_structure(
243 new external_value(PARAM_INT, 'User ID'),
246 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
247 current user', VALUE_DEFAULT, 0)
255 * @deprecated since Moodle 3.6
256 * @param array $userids array of user IDs.
257 * @param int $userid The id of the user we are creating the contacts for
258 * @return external_description
261 public static function create_contacts($userids, $userid = 0) {
264 // Check if messaging is enabled.
265 if (empty($CFG->messaging)) {
266 throw new moodle_exception('disabled', 'message');
269 if (empty($userid)) {
274 $context = context_system::instance();
275 self::validate_context($context);
277 $capability = 'moodle/site:manageallmessaging';
278 if (($USER->id != $userid) && !has_capability($capability, $context)) {
279 throw new required_capability_exception($context, $capability, 'nopermissions', '');
282 $params = array('userids' => $userids, 'userid' => $userid);
283 $params = self::validate_parameters(self::create_contacts_parameters(), $params);
286 foreach ($params['userids'] as $id) {
287 if (!message_add_contact($id, 0, $userid)) {
291 'warningcode' => 'contactnotcreated',
292 'message' => 'The contact could not be created'
300 * Create contacts return description.
302 * @deprecated since Moodle 3.6
303 * @return external_description
306 public static function create_contacts_returns() {
307 return new external_warnings();
311 * Marking the method as deprecated.
315 public static function create_contacts_is_deprecated() {
320 * Delete contacts parameters description.
322 * @return external_function_parameters
325 public static function delete_contacts_parameters() {
326 return new external_function_parameters(
328 'userids' => new external_multiple_structure(
329 new external_value(PARAM_INT, 'User ID'),
332 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
333 current user', VALUE_DEFAULT, 0)
341 * @param array $userids array of user IDs.
342 * @param int $userid The id of the user we are deleting the contacts for
346 public static function delete_contacts($userids, $userid = 0) {
349 // Check if messaging is enabled.
350 if (empty($CFG->messaging)) {
351 throw new moodle_exception('disabled', 'message');
354 if (empty($userid)) {
359 $context = context_system::instance();
360 self::validate_context($context);
362 $capability = 'moodle/site:manageallmessaging';
363 if (($USER->id != $userid) && !has_capability($capability, $context)) {
364 throw new required_capability_exception($context, $capability, 'nopermissions', '');
367 $params = array('userids' => $userids, 'userid' => $userid);
368 $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
370 foreach ($params['userids'] as $id) {
371 \core_message\api::remove_contact($userid, $id);
378 * Delete contacts return description.
380 * @return external_description
383 public static function delete_contacts_returns() {
388 * Block user parameters description.
390 * @return external_function_parameters
392 public static function block_user_parameters() {
393 return new external_function_parameters(
395 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
396 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
404 * @param int $userid The id of the user who is blocking
405 * @param int $blockeduserid The id of the user being blocked
406 * @return external_description
408 public static function block_user(int $userid, int $blockeduserid) {
411 // Check if messaging is enabled.
412 if (empty($CFG->messaging)) {
413 throw new moodle_exception('disabled', 'message');
417 $context = context_system::instance();
418 self::validate_context($context);
420 $capability = 'moodle/site:manageallmessaging';
421 if (($USER->id != $userid) && !has_capability($capability, $context)) {
422 throw new required_capability_exception($context, $capability, 'nopermissions', '');
425 $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
426 $params = self::validate_parameters(self::block_user_parameters(), $params);
428 if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
429 \core_message\api::block_user($params['userid'], $params['blockeduserid']);
436 * Block user return description.
438 * @return external_description
440 public static function block_user_returns() {
441 return new external_warnings();
445 * Unblock user parameters description.
447 * @return external_function_parameters
449 public static function unblock_user_parameters() {
450 return new external_function_parameters(
452 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
453 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
461 * @param int $userid The id of the user who is unblocking
462 * @param int $unblockeduserid The id of the user being unblocked
464 public static function unblock_user(int $userid, int $unblockeduserid) {
467 // Check if messaging is enabled.
468 if (empty($CFG->messaging)) {
469 throw new moodle_exception('disabled', 'message');
473 $context = context_system::instance();
474 self::validate_context($context);
476 $capability = 'moodle/site:manageallmessaging';
477 if (($USER->id != $userid) && !has_capability($capability, $context)) {
478 throw new required_capability_exception($context, $capability, 'nopermissions', '');
481 $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
482 $params = self::validate_parameters(self::unblock_user_parameters(), $params);
484 \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
490 * Unblock user return description.
492 * @return external_description
494 public static function unblock_user_returns() {
495 return new external_warnings();
499 * Block contacts parameters description.
501 * @deprecated since Moodle 3.6
502 * @return external_function_parameters
505 public static function block_contacts_parameters() {
506 return new external_function_parameters(
508 'userids' => new external_multiple_structure(
509 new external_value(PARAM_INT, 'User ID'),
512 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
513 current user', VALUE_DEFAULT, 0)
521 * @deprecated since Moodle 3.6
522 * @param array $userids array of user IDs.
523 * @param int $userid The id of the user we are blocking the contacts for
524 * @return external_description
527 public static function block_contacts($userids, $userid = 0) {
530 // Check if messaging is enabled.
531 if (empty($CFG->messaging)) {
532 throw new moodle_exception('disabled', 'message');
535 if (empty($userid)) {
540 $context = context_system::instance();
541 self::validate_context($context);
543 $capability = 'moodle/site:manageallmessaging';
544 if (($USER->id != $userid) && !has_capability($capability, $context)) {
545 throw new required_capability_exception($context, $capability, 'nopermissions', '');
548 $params = array('userids' => $userids, 'userid' => $userid);
549 $params = self::validate_parameters(self::block_contacts_parameters(), $params);
552 foreach ($params['userids'] as $id) {
553 if (!message_block_contact($id, $userid)) {
557 'warningcode' => 'contactnotblocked',
558 'message' => 'The contact could not be blocked'
566 * Block contacts return description.
568 * @deprecated since Moodle 3.6
569 * @return external_description
572 public static function block_contacts_returns() {
573 return new external_warnings();
577 * Marking the method as deprecated.
581 public static function block_contacts_is_deprecated() {
586 * Unblock contacts parameters description.
588 * @deprecated since Moodle 3.6
589 * @return external_function_parameters
592 public static function unblock_contacts_parameters() {
593 return new external_function_parameters(
595 'userids' => new external_multiple_structure(
596 new external_value(PARAM_INT, 'User ID'),
599 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
600 current user', VALUE_DEFAULT, 0)
608 * @param array $userids array of user IDs.
609 * @param int $userid The id of the user we are unblocking the contacts for
613 public static function unblock_contacts($userids, $userid = 0) {
616 // Check if messaging is enabled.
617 if (empty($CFG->messaging)) {
618 throw new moodle_exception('disabled', 'message');
621 if (empty($userid)) {
626 $context = context_system::instance();
627 self::validate_context($context);
629 $capability = 'moodle/site:manageallmessaging';
630 if (($USER->id != $userid) && !has_capability($capability, $context)) {
631 throw new required_capability_exception($context, $capability, 'nopermissions', '');
634 $params = array('userids' => $userids, 'userid' => $userid);
635 $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
637 foreach ($params['userids'] as $id) {
638 message_unblock_contact($id, $userid);
645 * Unblock contacts return description.
647 * @deprecated since Moodle 3.6
648 * @return external_description
651 public static function unblock_contacts_returns() {
656 * Marking the method as deprecated.
660 public static function unblock_contacts_is_deprecated() {
665 * Returns contact requests parameters description.
667 * @return external_function_parameters
669 public static function get_contact_requests_parameters() {
670 return new external_function_parameters(
672 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for'),
673 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
674 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
680 * Handles returning the contact requests for a user.
682 * This also includes the user data necessary to display information
685 * It will not include blocked users.
687 * @param int $userid The id of the user we want to get the contact requests for
688 * @param int $limitfrom
689 * @param int $limitnum
691 public static function get_contact_requests(int $userid, int $limitfrom = 0, int $limitnum = 0) {
694 // Check if messaging is enabled.
695 if (empty($CFG->messaging)) {
696 throw new moodle_exception('disabled', 'message');
700 $context = context_system::instance();
701 self::validate_context($context);
703 $capability = 'moodle/site:manageallmessaging';
704 if (($USER->id != $userid) && !has_capability($capability, $context)) {
705 throw new required_capability_exception($context, $capability, 'nopermissions', '');
710 'limitfrom' => $limitfrom,
711 'limitnum' => $limitnum
713 $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
715 return \core_message\api::get_contact_requests($params['userid'], $params['limitfrom'], $params['limitnum']);
719 * Returns the contact requests return description.
721 * @return external_description
723 public static function get_contact_requests_returns() {
724 return new external_multiple_structure(
725 self::get_conversation_member_structure()
730 * Returns get conversation members parameters description.
732 * @return external_function_parameters
734 public static function get_conversation_members_parameters() {
735 return new external_function_parameters(
737 'userid' => new external_value(PARAM_INT, 'The id of the user we are performing this action on behalf of'),
738 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation'),
739 'includecontactrequests' => new external_value(PARAM_BOOL, 'Do we want to include contact requests?',
740 VALUE_DEFAULT, false),
741 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
742 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
748 * Returns a list of conversation members.
750 * @param int $userid The user we are returning the conversation members for, used by helper::get_member_info.
751 * @param int $conversationid The id of the conversation
752 * @param bool $includecontactrequests Do we want to include contact requests with this data?
753 * @param int $limitfrom
754 * @param int $limitnum
757 public static function get_conversation_members(int $userid, int $conversationid, bool $includecontactrequests = false,
758 int $limitfrom = 0, int $limitnum = 0) {
761 // Check if messaging is enabled.
762 if (empty($CFG->messaging)) {
763 throw new moodle_exception('disabled', 'message');
767 $context = context_system::instance();
768 self::validate_context($context);
770 $capability = 'moodle/site:manageallmessaging';
771 if (($USER->id != $userid) && !has_capability($capability, $context)) {
772 throw new required_capability_exception($context, $capability, 'nopermissions', '');
775 // The user needs to be a part of the conversation before querying who the members are.
776 if (!\core_message\api::is_user_in_conversation($userid, $conversationid)) {
777 throw new moodle_exception('You are not a member of this conversation.');
782 'conversationid' => $conversationid,
783 'includecontactrequests' => $includecontactrequests,
784 'limitfrom' => $limitfrom,
785 'limitnum' => $limitnum
787 self::validate_parameters(self::get_conversation_members_parameters(), $params);
789 return \core_message\api::get_conversation_members($userid, $conversationid, $includecontactrequests,
790 $limitfrom, $limitnum);
794 * Returns the get conversation members return description.
796 * @return external_description
798 public static function get_conversation_members_returns() {
799 return new external_multiple_structure(
800 self::get_conversation_member_structure(true)
805 * Creates a contact request parameters description.
807 * @return external_function_parameters
809 public static function create_contact_request_parameters() {
810 return new external_function_parameters(
812 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
813 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
819 * Creates a contact request.
821 * @param int $userid The id of the user who is creating the contact request
822 * @param int $requesteduserid The id of the user being requested
824 public static function create_contact_request(int $userid, int $requesteduserid) {
827 // Check if messaging is enabled.
828 if (empty($CFG->messaging)) {
829 throw new moodle_exception('disabled', 'message');
833 $context = context_system::instance();
834 self::validate_context($context);
836 $capability = 'moodle/site:manageallmessaging';
837 if (($USER->id != $userid) && !has_capability($capability, $context)) {
838 throw new required_capability_exception($context, $capability, 'nopermissions', '');
841 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
842 $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
844 if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
847 'itemid' => $params['requesteduserid'],
848 'warningcode' => 'cannotcreatecontactrequest',
849 'message' => 'You are unable to create a contact request for this user'
854 if (!\core_message\api::does_contact_request_exist($params['userid'], $params['requesteduserid'])) {
855 \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
862 * Creates a contact request return description.
864 * @return external_description
866 public static function create_contact_request_returns() {
867 return new external_warnings();
871 * Confirm a contact request parameters description.
873 * @return external_function_parameters
875 public static function confirm_contact_request_parameters() {
876 return new external_function_parameters(
878 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
879 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
885 * Confirm a contact request.
887 * @param int $userid The id of the user who is creating the contact request
888 * @param int $requesteduserid The id of the user being requested
890 public static function confirm_contact_request(int $userid, int $requesteduserid) {
893 // Check if messaging is enabled.
894 if (empty($CFG->messaging)) {
895 throw new moodle_exception('disabled', 'message');
899 $context = context_system::instance();
900 self::validate_context($context);
902 $capability = 'moodle/site:manageallmessaging';
903 if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
904 throw new required_capability_exception($context, $capability, 'nopermissions', '');
907 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
908 $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
910 \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
916 * Confirm a contact request return description.
918 * @return external_description
920 public static function confirm_contact_request_returns() {
921 return new external_warnings();
925 * Declines a contact request parameters description.
927 * @return external_function_parameters
929 public static function decline_contact_request_parameters() {
930 return new external_function_parameters(
932 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
933 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
939 * Declines a contact request.
941 * @param int $userid The id of the user who is creating the contact request
942 * @param int $requesteduserid The id of the user being requested
944 public static function decline_contact_request(int $userid, int $requesteduserid) {
947 // Check if messaging is enabled.
948 if (empty($CFG->messaging)) {
949 throw new moodle_exception('disabled', 'message');
953 $context = context_system::instance();
954 self::validate_context($context);
956 $capability = 'moodle/site:manageallmessaging';
957 if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
958 throw new required_capability_exception($context, $capability, 'nopermissions', '');
961 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
962 $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
964 \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
970 * Declines a contact request return description.
972 * @return external_description
974 public static function decline_contact_request_returns() {
975 return new external_warnings();
979 * Return the structure of a message area contact.
981 * @return external_single_structure
984 private static function get_messagearea_contact_structure() {
985 return new external_single_structure(
987 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
988 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
989 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
990 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
991 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
992 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
993 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
994 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
995 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
996 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
997 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
998 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
999 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1000 VALUE_DEFAULT, null),
1006 * Return the structure of a conversation.
1008 * @return external_single_structure
1012 private static function get_conversation_structure() {
1013 return new external_single_structure(
1015 'id' => new external_value(PARAM_INT, 'The conversation id'),
1016 'name' => new external_value(PARAM_NOTAGS, 'The conversation name, if set', VALUE_DEFAULT, null),
1017 'subname' => new external_value(PARAM_NOTAGS, 'A subtitle for the conversation name, if set', VALUE_DEFAULT, null),
1018 'imageurl' => new external_value(PARAM_URL, 'A link to the conversation picture, if set', VALUE_DEFAULT, null),
1019 'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group)'),
1020 'membercount' => new external_value(PARAM_INT, 'Total number of conversation members'),
1021 'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked conversation this conversation as a favourite'),
1022 'isread' => new external_value(PARAM_BOOL, 'If the user has read all messages in the conversation'),
1023 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1024 VALUE_DEFAULT, null),
1025 'members' => new external_multiple_structure(
1026 self::get_conversation_member_structure(true)
1028 'messages' => new external_multiple_structure(
1029 self::get_conversation_message_structure()
1036 * Return the structure of a conversation member.
1038 * @param bool $includecontactrequests Are we including contact requests?
1039 * @param bool $includeconversations Are we including conversations?
1040 * @return external_single_structure
1043 private static function get_conversation_member_structure(bool $includecontactrequests = false,
1044 bool $includeconversations = false) {
1046 'id' => new external_value(PARAM_INT, 'The user id'),
1047 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1048 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1049 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1050 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1051 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1052 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1053 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
1054 'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
1055 'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
1056 'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
1059 if ($includecontactrequests) {
1060 $result['contactrequests'] = new external_multiple_structure(
1061 new external_single_structure(
1063 'id' => new external_value(PARAM_INT, 'The id of the message'),
1064 'userid' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1065 'requesteduserid' => new external_value(PARAM_RAW, 'The text of the message'),
1066 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1068 ), 'The contact requests', VALUE_OPTIONAL
1072 if ($includeconversations) {
1073 $result['conversations'] = new external_multiple_structure(new external_single_structure(
1075 'id' => new external_value(PARAM_INT, 'Conversations id'),
1076 'type' => new external_value(PARAM_INT, 'Conversation type: private or public'),
1077 'name' => new external_value(PARAM_TEXT, 'Multilang compatible conversation name'. VALUE_OPTIONAL),
1078 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the conversation'),
1079 ), 'information about conversation', VALUE_OPTIONAL),
1080 'Conversations between users', VALUE_OPTIONAL
1084 return new external_single_structure(
1090 * Return the structure of a message area message.
1092 * @return external_single_structure
1095 private static function get_conversation_message_structure() {
1096 return new external_single_structure(
1098 'id' => new external_value(PARAM_INT, 'The id of the message'),
1099 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1100 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1101 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1107 * Return the structure of a message area message.
1109 * @return external_single_structure
1112 private static function get_messagearea_message_structure() {
1113 return new external_single_structure(
1115 'id' => new external_value(PARAM_INT, 'The id of the message'),
1116 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1117 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
1118 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1119 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
1120 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
1121 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
1122 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
1123 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1124 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
1130 * Get messagearea search users in course parameters.
1132 * @deprecated since 3.6
1134 * @return external_function_parameters
1137 public static function data_for_messagearea_search_users_in_course_parameters() {
1138 return new external_function_parameters(
1140 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1141 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
1142 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1143 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1144 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1150 * Get messagearea search users in course results.
1152 * @deprecated since 3.6
1154 * NOTE: We are deprecating this function but not search_users_in_course API function for backwards compatibility
1155 * with messaging UI. But should be removed once new group messaging UI is in place and old messaging UI is removed.
1156 * Followup: MDL-63915
1158 * @param int $userid The id of the user who is performing the search
1159 * @param int $courseid The id of the course
1160 * @param string $search The string being searched
1161 * @param int $limitfrom
1162 * @param int $limitnum
1164 * @throws moodle_exception
1167 public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
1169 global $CFG, $PAGE, $USER;
1171 // Check if messaging is enabled.
1172 if (empty($CFG->messaging)) {
1173 throw new moodle_exception('disabled', 'message');
1176 $systemcontext = context_system::instance();
1179 'userid' => $userid,
1180 'courseid' => $courseid,
1181 'search' => $search,
1182 'limitfrom' => $limitfrom,
1183 'limitnum' => $limitnum
1185 self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
1186 self::validate_context($systemcontext);
1188 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1189 throw new moodle_exception('You do not have permission to perform this action.');
1192 $users = \core_message\api::search_users_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
1193 $results = new \core_message\output\messagearea\user_search_results($users);
1195 $renderer = $PAGE->get_renderer('core_message');
1196 return $results->export_for_template($renderer);
1200 * Get messagearea search users in course returns.
1202 * @deprecated since 3.6
1204 * @return external_single_structure
1207 public static function data_for_messagearea_search_users_in_course_returns() {
1208 return new external_single_structure(
1210 'contacts' => new external_multiple_structure(
1211 self::get_messagearea_contact_structure()
1218 * Marking the method as deprecated.
1222 public static function data_for_messagearea_search_users_in_course_is_deprecated() {
1227 * Get messagearea search users parameters.
1229 * @deprecated since 3.6
1231 * @return external_function_parameters
1234 public static function data_for_messagearea_search_users_parameters() {
1235 return new external_function_parameters(
1237 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1238 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1239 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1245 * Get messagearea search users results.
1247 * @deprecated since 3.6
1249 * NOTE: We are deprecating this function but not search_users API function for backwards compatibility
1250 * with messaging UI. But should be removed once new group messaging UI is in place and old messaging UI is removed.
1251 * Followup: MDL-63915
1253 * @param int $userid The id of the user who is performing the search
1254 * @param string $search The string being searched
1255 * @param int $limitnum
1257 * @throws moodle_exception
1260 public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1261 global $CFG, $PAGE, $USER;
1263 // Check if messaging is enabled.
1264 if (empty($CFG->messaging)) {
1265 throw new moodle_exception('disabled', 'message');
1268 $systemcontext = context_system::instance();
1271 'userid' => $userid,
1272 'search' => $search,
1273 'limitnum' => $limitnum
1275 self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1276 self::validate_context($systemcontext);
1278 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1279 throw new moodle_exception('You do not have permission to perform this action.');
1282 list($contacts, $courses, $noncontacts) = \core_message\api::search_users($userid, $search, $limitnum);
1283 $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1285 $renderer = $PAGE->get_renderer('core_message');
1286 return $search->export_for_template($renderer);
1290 * Get messagearea search users returns.
1292 * @deprecated since 3.6
1294 * @return external_single_structure
1297 public static function data_for_messagearea_search_users_returns() {
1298 return new external_single_structure(
1300 'contacts' => new external_multiple_structure(
1301 self::get_messagearea_contact_structure()
1303 'courses' => new external_multiple_structure(
1304 new external_single_structure(
1306 'id' => new external_value(PARAM_INT, 'The course id'),
1307 'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1308 'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1312 'noncontacts' => new external_multiple_structure(
1313 self::get_messagearea_contact_structure()
1320 * Marking the method as deprecated.
1324 public static function data_for_messagearea_search_users_is_deprecated() {
1329 * Get messagearea message search users parameters.
1331 * @return external_function_parameters
1334 public static function message_search_users_parameters() {
1335 return new external_function_parameters(
1337 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1338 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1339 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1340 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1346 * Get search users results.
1348 * @param int $userid The id of the user who is performing the search
1349 * @param string $search The string being searched
1350 * @param int $limitfrom
1351 * @param int $limitnum
1353 * @throws moodle_exception
1356 public static function message_search_users($userid, $search, $limitfrom = 0, $limitnum = 0) {
1359 // Check if messaging is enabled.
1360 if (empty($CFG->messaging)) {
1361 throw new moodle_exception('disabled', 'message');
1364 $systemcontext = context_system::instance();
1367 'userid' => $userid,
1368 'search' => $search,
1369 'limitfrom' => $limitfrom,
1370 'limitnum' => $limitnum
1372 $params = self::validate_parameters(self::message_search_users_parameters(), $params);
1373 self::validate_context($systemcontext);
1375 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1376 throw new moodle_exception('You do not have permission to perform this action.');
1379 list($contacts, $noncontacts) = \core_message\api::message_search_users(
1382 $params['limitfrom'],
1383 $params['limitnum']);
1385 return array('contacts' => $contacts, 'noncontacts' => $noncontacts);
1389 * Get messagearea message search users returns.
1391 * @return external_single_structure
1394 public static function message_search_users_returns() {
1395 return new external_single_structure(
1397 'contacts' => new external_multiple_structure(
1398 self::get_conversation_member_structure(false, true)
1400 'noncontacts' => new external_multiple_structure(
1401 self::get_conversation_member_structure(false, true)
1408 * Get messagearea search messages parameters.
1410 * @return external_function_parameters
1413 public static function data_for_messagearea_search_messages_parameters() {
1414 return new external_function_parameters(
1416 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1417 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1418 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1419 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1425 * Get messagearea search messages results.
1427 * @param int $userid The id of the user who is performing the search
1428 * @param string $search The string being searched
1429 * @param int $limitfrom
1430 * @param int $limitnum
1432 * @throws moodle_exception
1435 public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1436 global $CFG, $PAGE, $USER;
1438 // Check if messaging is enabled.
1439 if (empty($CFG->messaging)) {
1440 throw new moodle_exception('disabled', 'message');
1443 $systemcontext = context_system::instance();
1446 'userid' => $userid,
1447 'search' => $search,
1448 'limitfrom' => $limitfrom,
1449 'limitnum' => $limitnum
1452 self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1453 self::validate_context($systemcontext);
1455 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1456 throw new moodle_exception('You do not have permission to perform this action.');
1459 $messages = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
1460 $results = new \core_message\output\messagearea\message_search_results($messages);
1462 $renderer = $PAGE->get_renderer('core_message');
1463 return $results->export_for_template($renderer);
1467 * Get messagearea search messages returns.
1469 * @return external_single_structure
1472 public static function data_for_messagearea_search_messages_returns() {
1473 return new external_single_structure(
1475 'contacts' => new external_multiple_structure(
1476 self::get_messagearea_contact_structure()
1483 * Get conversations parameters.
1485 * @return external_function_parameters
1488 public static function get_conversations_parameters() {
1489 return new external_function_parameters(
1491 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1492 'limitfrom' => new external_value(PARAM_INT, 'The offset to start at', VALUE_DEFAULT, 0),
1493 'limitnum' => new external_value(PARAM_INT, 'Limit number of conversations to this', VALUE_DEFAULT, 0),
1494 'type' => new external_value(PARAM_INT, 'Filter by type', VALUE_DEFAULT, null),
1495 'favourites' => new external_value(PARAM_BOOL, 'Whether to restrict the results to contain NO favourite
1496 conversations (false), ONLY favourite conversation (true), or ignore any restriction altogether (null)',
1497 VALUE_DEFAULT, null),
1504 * Get the list of conversations for the user.
1506 * @param int $userid The id of the user who is performing the search
1507 * @param int $limitfrom
1508 * @param int $limitnum
1509 * @param int|null $type
1510 * @param bool|null $favourites
1512 * @throws \moodle_exception if the messaging feature is disabled on the site.
1515 public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null) {
1518 // All the standard BL checks.
1519 if (empty($CFG->messaging)) {
1520 throw new moodle_exception('disabled', 'message');
1524 'userid' => $userid,
1525 'limitfrom' => $limitfrom,
1526 'limitnum' => $limitnum,
1528 'favourites' => $favourites
1530 self::validate_parameters(self::get_conversations_parameters(), $params);
1532 $systemcontext = context_system::instance();
1533 self::validate_context($systemcontext);
1535 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1536 throw new moodle_exception('You do not have permission to perform this action.');
1539 $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum, $type, $favourites);
1540 return (object) ['conversations' => $conversations];
1544 * Get conversations returns.
1546 * @return external_single_structure
1549 public static function get_conversations_returns() {
1550 return new external_single_structure(
1552 'conversations' => new external_multiple_structure(
1553 self::get_conversation_structure()
1560 * The messagearea conversations parameters.
1562 * @deprecated since 3.6
1563 * @return external_function_parameters
1566 public static function data_for_messagearea_conversations_parameters() {
1567 return new external_function_parameters(
1569 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1570 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1571 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1577 * Get messagearea conversations.
1579 * NOTE FOR FINAL DEPRECATION:
1580 * When removing this method, please also consider removal of get_conversations_legacy_formatter()
1581 * from the \core_message\helper class. This helper method was used solely to format the new get_conversations() return data
1582 * into the old format used here, and in message/index.php. If we no longer need either of these, then that method can be
1585 * @deprecated since 3.6
1586 * @param int $userid The id of the user who we are viewing conversations for
1587 * @param int $limitfrom
1588 * @param int $limitnum
1590 * @throws moodle_exception
1593 public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1594 global $CFG, $PAGE, $USER;
1596 // Check if messaging is enabled.
1597 if (empty($CFG->messaging)) {
1598 throw new moodle_exception('disabled', 'message');
1601 $systemcontext = context_system::instance();
1604 'userid' => $userid,
1605 'limitfrom' => $limitfrom,
1606 'limitnum' => $limitnum
1608 self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1609 self::validate_context($systemcontext);
1611 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1612 throw new moodle_exception('You do not have permission to perform this action.');
1615 $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum);
1617 // Format the conversations in the legacy style, as the get_conversations method has since been changed.
1618 $conversations = \core_message\helper::get_conversations_legacy_formatter($conversations);
1620 $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1622 $renderer = $PAGE->get_renderer('core_message');
1623 return $conversations->export_for_template($renderer);
1627 * The messagearea conversations return structure.
1629 * @deprecated since 3.6
1630 * @return external_single_structure
1633 public static function data_for_messagearea_conversations_returns() {
1634 return new external_single_structure(
1636 'contacts' => new external_multiple_structure(
1637 self::get_messagearea_contact_structure()
1644 * Marking the method as deprecated.
1648 public static function data_for_messagearea_conversations_is_deprecated() {
1653 * The messagearea contacts return parameters.
1655 * @deprecated since 3.6
1656 * @return external_function_parameters
1659 public static function data_for_messagearea_contacts_parameters() {
1660 return self::data_for_messagearea_conversations_parameters();
1664 * Get messagearea contacts parameters.
1666 * @deprecated since 3.6
1667 * @param int $userid The id of the user who we are viewing conversations for
1668 * @param int $limitfrom
1669 * @param int $limitnum
1671 * @throws moodle_exception
1674 public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1675 global $CFG, $PAGE, $USER;
1677 // Check if messaging is enabled.
1678 if (empty($CFG->messaging)) {
1679 throw new moodle_exception('disabled', 'message');
1682 $systemcontext = context_system::instance();
1685 'userid' => $userid,
1686 'limitfrom' => $limitfrom,
1687 'limitnum' => $limitnum
1689 self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1690 self::validate_context($systemcontext);
1692 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1693 throw new moodle_exception('You do not have permission to perform this action.');
1696 $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
1697 $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1699 $renderer = $PAGE->get_renderer('core_message');
1700 return $contacts->export_for_template($renderer);
1704 * The messagearea contacts return structure.
1706 * @deprecated since 3.6
1707 * @return external_single_structure
1710 public static function data_for_messagearea_contacts_returns() {
1711 return self::data_for_messagearea_conversations_returns();
1715 * Marking the method as deprecated.
1719 public static function data_for_messagearea_contacts_is_deprecated() {
1724 * The messagearea messages parameters.
1726 * @deprecated since 3.6
1727 * @return external_function_parameters
1730 public static function data_for_messagearea_messages_parameters() {
1731 return new external_function_parameters(
1733 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1734 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1735 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1736 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1737 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1738 'timefrom' => new external_value(PARAM_INT,
1739 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1745 * Get messagearea messages.
1747 * @deprecated since 3.6
1748 * @param int $currentuserid The current user's id
1749 * @param int $otheruserid The other user's id
1750 * @param int $limitfrom
1751 * @param int $limitnum
1752 * @param boolean $newest
1754 * @throws moodle_exception
1757 public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
1758 $newest = false, $timefrom = 0) {
1759 global $CFG, $PAGE, $USER;
1761 // Check if messaging is enabled.
1762 if (empty($CFG->messaging)) {
1763 throw new moodle_exception('disabled', 'message');
1766 $systemcontext = context_system::instance();
1769 'currentuserid' => $currentuserid,
1770 'otheruserid' => $otheruserid,
1771 'limitfrom' => $limitfrom,
1772 'limitnum' => $limitnum,
1773 'newest' => $newest,
1774 'timefrom' => $timefrom,
1776 self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
1777 self::validate_context($systemcontext);
1779 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1780 throw new moodle_exception('You do not have permission to perform this action.');
1784 $sort = 'timecreated DESC';
1786 $sort = 'timecreated ASC';
1789 // We need to enforce a one second delay on messages to avoid race conditions of current
1790 // messages still being sent.
1792 // There is a chance that we could request messages before the current time's
1793 // second has elapsed and while other messages are being sent in that same second. In which
1794 // case those messages will be lost.
1796 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1797 if (!empty($timefrom)) {
1798 $timeto = time() - 1;
1803 // No requesting messages from the current time, as stated above.
1804 if ($timefrom == time()) {
1807 $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
1808 $limitnum, $sort, $timefrom, $timeto);
1811 $messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
1813 $renderer = $PAGE->get_renderer('core_message');
1814 return $messages->export_for_template($renderer);
1818 * The messagearea messages return structure.
1820 * @deprecated since 3.6
1821 * @return external_single_structure
1824 public static function data_for_messagearea_messages_returns() {
1825 return new external_single_structure(
1827 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
1828 the messages on behalf of?'),
1829 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1830 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1831 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
1832 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1833 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1834 'messages' => new external_multiple_structure(
1835 self::get_messagearea_message_structure()
1837 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
1843 * Marking the method as deprecated.
1847 public static function data_for_messagearea_messages_is_deprecated() {
1852 * The conversation messages parameters.
1854 * @return external_function_parameters
1857 public static function get_conversation_messages_parameters() {
1858 return new external_function_parameters(
1860 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1861 'convid' => new external_value(PARAM_INT, 'The conversation id'),
1862 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1863 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1864 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1865 'timefrom' => new external_value(PARAM_INT,
1866 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1872 * Get conversation messages.
1874 * @param int $currentuserid The current user's id.
1875 * @param int $convid The conversation id.
1876 * @param int $limitfrom Return a subset of records, starting at this point (optional).
1877 * @param int $limitnum Return a subset comprising this many records in total (optional, required if $limitfrom is set).
1878 * @param bool $newest True for getting first newest messages, false otherwise.
1879 * @param int $timefrom The time from the conversation messages to get.
1880 * @return stdClass The messages and members who have sent some of these messages.
1881 * @throws moodle_exception
1884 public static function get_conversation_messages(int $currentuserid, int $convid, int $limitfrom = 0, int $limitnum = 0,
1885 bool $newest = false, int $timefrom = 0) {
1886 global $CFG, $PAGE, $USER;
1888 // Check if messaging is enabled.
1889 if (empty($CFG->messaging)) {
1890 throw new moodle_exception('disabled', 'message');
1893 $systemcontext = context_system::instance();
1896 'currentuserid' => $currentuserid,
1897 'convid' => $convid,
1898 'limitfrom' => $limitfrom,
1899 'limitnum' => $limitnum,
1900 'newest' => $newest,
1901 'timefrom' => $timefrom,
1903 self::validate_parameters(self::get_conversation_messages_parameters(), $params);
1904 self::validate_context($systemcontext);
1906 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1907 throw new moodle_exception('You do not have permission to perform this action.');
1910 $sort = $newest ? 'timecreated DESC' : 'timecreated ASC';
1912 // We need to enforce a one second delay on messages to avoid race conditions of current
1913 // messages still being sent.
1915 // There is a chance that we could request messages before the current time's
1916 // second has elapsed and while other messages are being sent in that same second. In which
1917 // case those messages will be lost.
1919 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1920 $timeto = empty($timefrom) ? 0 : time() - 1;
1922 // No requesting messages from the current time, as stated above.
1923 if ($timefrom == time()) {
1926 $messages = \core_message\api::get_conversation_messages($currentuserid, $convid, $limitfrom,
1927 $limitnum, $sort, $timefrom, $timeto);
1934 * The messagearea messages return structure.
1936 * @return external_single_structure
1939 public static function get_conversation_messages_returns() {
1940 return new external_single_structure(
1942 'id' => new external_value(PARAM_INT, 'The conversation id'),
1943 'members' => new external_multiple_structure(
1944 self::get_conversation_member_structure()
1946 'messages' => new external_multiple_structure(
1947 self::get_conversation_message_structure()
1954 * The get most recent message return parameters.
1956 * @deprecated since 3.6
1957 * @return external_function_parameters
1960 public static function data_for_messagearea_get_most_recent_message_parameters() {
1961 return new external_function_parameters(
1963 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1964 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1970 * Get the most recent message in a conversation.
1972 * @deprecated since 3.6
1973 * @param int $currentuserid The current user's id
1974 * @param int $otheruserid The other user's id
1976 * @throws moodle_exception
1979 public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
1980 global $CFG, $PAGE, $USER;
1982 // Check if messaging is enabled.
1983 if (empty($CFG->messaging)) {
1984 throw new moodle_exception('disabled', 'message');
1987 $systemcontext = context_system::instance();
1990 'currentuserid' => $currentuserid,
1991 'otheruserid' => $otheruserid
1993 self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
1994 self::validate_context($systemcontext);
1996 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1997 throw new moodle_exception('You do not have permission to perform this action.');
2000 $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
2001 $message = new \core_message\output\messagearea\message($message);
2003 $renderer = $PAGE->get_renderer('core_message');
2004 return $message->export_for_template($renderer);
2008 * The get most recent message return structure.
2010 * @deprecated since 3.6
2011 * @return external_single_structure
2014 public static function data_for_messagearea_get_most_recent_message_returns() {
2015 return self::get_messagearea_message_structure();
2019 * Marking the method as deprecated.
2023 public static function data_for_messagearea_get_most_recent_message_is_deprecated() {
2028 * The get profile parameters.
2030 * @deprecated since 3.6
2031 * @return external_function_parameters
2034 public static function data_for_messagearea_get_profile_parameters() {
2035 return new external_function_parameters(
2037 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2038 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
2044 * Get the profile information for a contact.
2046 * @deprecated since 3.6
2047 * @param int $currentuserid The current user's id
2048 * @param int $otheruserid The id of the user whose profile we are viewing
2050 * @throws moodle_exception
2053 public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
2054 global $CFG, $PAGE, $USER;
2056 // Check if messaging is enabled.
2057 if (empty($CFG->messaging)) {
2058 throw new moodle_exception('disabled', 'message');
2061 $systemcontext = context_system::instance();
2064 'currentuserid' => $currentuserid,
2065 'otheruserid' => $otheruserid
2067 self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
2068 self::validate_context($systemcontext);
2070 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2071 throw new moodle_exception('You do not have permission to perform this action.');
2074 $profile = \core_message\api::get_profile($currentuserid, $otheruserid);
2075 $profile = new \core_message\output\messagearea\profile($profile);
2077 $renderer = $PAGE->get_renderer('core_message');
2078 return $profile->export_for_template($renderer);
2082 * The get profile return structure.
2084 * @deprecated since 3.6
2085 * @return external_single_structure
2088 public static function data_for_messagearea_get_profile_returns() {
2089 return new external_single_structure(
2091 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
2092 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
2093 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
2094 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
2095 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
2096 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
2097 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
2098 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2099 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2100 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
2101 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
2107 * Marking the method as deprecated.
2111 public static function data_for_messagearea_get_profile_is_deprecated() {
2116 * Get contacts parameters description.
2118 * @return external_function_parameters
2121 public static function get_contacts_parameters() {
2122 return new external_function_parameters(array());
2128 * @return external_description
2131 public static function get_contacts() {
2132 global $CFG, $PAGE, $USER;
2134 // Check if messaging is enabled.
2135 if (empty($CFG->messaging)) {
2136 throw new moodle_exception('disabled', 'message');
2139 require_once($CFG->dirroot . '/user/lib.php');
2141 $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
2142 $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
2143 foreach ($contacts as $contact) {
2146 if (\core_message\helper::is_online($contact->lastaccess)) {
2150 $newcontact = array(
2151 'id' => $contact->id,
2152 'fullname' => fullname($contact),
2153 'unread' => $contact->messagecount
2156 $userpicture = new user_picture($contact);
2157 $userpicture->size = 1; // Size f1.
2158 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2159 $userpicture->size = 0; // Size f2.
2160 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2162 $allcontacts[$mode][$contact->id] = $newcontact;
2165 $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
2166 foreach ($strangers as $contact) {
2167 $newcontact = array(
2168 'id' => $contact->id,
2169 'fullname' => fullname($contact),
2170 'unread' => $contact->messagecount
2173 $userpicture = new user_picture($contact);
2174 $userpicture->size = 1; // Size f1.
2175 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2176 $userpicture->size = 0; // Size f2.
2177 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2179 $allcontacts['strangers'][$contact->id] = $newcontact;
2182 // Add noreply user and support user to the list, if they don't exist.
2183 $supportuser = core_user::get_support_user();
2184 if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
2185 $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
2186 if ($supportuser->messagecount > 0) {
2187 $supportuser->fullname = fullname($supportuser);
2188 $supportuser->unread = $supportuser->messagecount;
2189 $allcontacts['strangers'][$supportuser->id] = $supportuser;
2193 $noreplyuser = core_user::get_noreply_user();
2194 if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
2195 $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
2196 if ($noreplyuser->messagecount > 0) {
2197 $noreplyuser->fullname = fullname($noreplyuser);
2198 $noreplyuser->unread = $noreplyuser->messagecount;
2199 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
2203 return $allcontacts;
2207 * Get contacts return description.
2209 * @return external_description
2212 public static function get_contacts_returns() {
2213 return new external_single_structure(
2215 'online' => new external_multiple_structure(
2216 new external_single_structure(
2218 'id' => new external_value(PARAM_INT, 'User ID'),
2219 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2220 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2221 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2222 'unread' => new external_value(PARAM_INT, 'Unread message count')
2225 'List of online contacts'
2227 'offline' => new external_multiple_structure(
2228 new external_single_structure(
2230 'id' => new external_value(PARAM_INT, 'User ID'),
2231 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2232 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2233 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2234 'unread' => new external_value(PARAM_INT, 'Unread message count')
2237 'List of offline contacts'
2239 'strangers' => new external_multiple_structure(
2240 new external_single_structure(
2242 'id' => new external_value(PARAM_INT, 'User ID'),
2243 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2244 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2245 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2246 'unread' => new external_value(PARAM_INT, 'Unread message count')
2249 'List of users that are not in the user\'s contact list but have sent a message'
2256 * Search contacts parameters description.
2258 * @return external_function_parameters
2261 public static function search_contacts_parameters() {
2262 return new external_function_parameters(
2264 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
2265 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
2266 VALUE_DEFAULT, false)
2274 * @param string $searchtext query string.
2275 * @param bool $onlymycourses limit the search to the user's courses only.
2276 * @return external_description
2279 public static function search_contacts($searchtext, $onlymycourses = false) {
2280 global $CFG, $USER, $PAGE;
2281 require_once($CFG->dirroot . '/user/lib.php');
2283 // Check if messaging is enabled.
2284 if (empty($CFG->messaging)) {
2285 throw new moodle_exception('disabled', 'message');
2288 require_once($CFG->libdir . '/enrollib.php');
2290 $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
2291 $params = self::validate_parameters(self::search_contacts_parameters(), $params);
2293 // Extra validation, we do not allow empty queries.
2294 if ($params['searchtext'] === '') {
2295 throw new moodle_exception('querystringcannotbeempty');
2298 $courseids = array();
2299 if ($params['onlymycourses']) {
2300 $mycourses = enrol_get_my_courses(array('id'));
2301 foreach ($mycourses as $mycourse) {
2302 $courseids[] = $mycourse->id;
2305 $courseids[] = SITEID;
2308 // Retrieving the users matching the query.
2309 $users = message_search_users($courseids, $params['searchtext']);
2311 foreach ($users as $user) {
2312 $results[$user->id] = $user;
2315 // Reorganising information.
2316 foreach ($results as &$user) {
2319 'fullname' => fullname($user)
2322 // Avoid undefined property notice as phone not specified.
2323 $user->phone1 = null;
2324 $user->phone2 = null;
2326 $userpicture = new user_picture($user);
2327 $userpicture->size = 1; // Size f1.
2328 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2329 $userpicture->size = 0; // Size f2.
2330 $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2339 * Search contacts return description.
2341 * @return external_description
2344 public static function search_contacts_returns() {
2345 return new external_multiple_structure(
2346 new external_single_structure(
2348 'id' => new external_value(PARAM_INT, 'User ID'),
2349 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2350 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2351 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
2359 * Get messages parameters description.
2361 * @return external_function_parameters
2364 public static function get_messages_parameters() {
2365 return new external_function_parameters(
2367 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2368 'useridfrom' => new external_value(
2369 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2371 'type' => new external_value(
2372 PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
2373 VALUE_DEFAULT, 'both'),
2374 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
2375 'newestfirst' => new external_value(
2376 PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
2377 VALUE_DEFAULT, true),
2378 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
2379 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
2385 * Get messages function implementation.
2388 * @throws invalid_parameter_exception
2389 * @throws moodle_exception
2390 * @param int $useridto the user id who received the message
2391 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2392 * @param string $type type of message to return, expected values: notifications, conversations and both
2393 * @param bool $read true for retreiving read messages, false for unread
2394 * @param bool $newestfirst true for ordering by newest first, false for oldest first
2395 * @param int $limitfrom limit from
2396 * @param int $limitnum limit num
2397 * @return external_description
2399 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
2400 $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
2403 $warnings = array();
2406 'useridto' => $useridto,
2407 'useridfrom' => $useridfrom,
2410 'newestfirst' => $newestfirst,
2411 'limitfrom' => $limitfrom,
2412 'limitnum' => $limitnum
2415 $params = self::validate_parameters(self::get_messages_parameters(), $params);
2417 $context = context_system::instance();
2418 self::validate_context($context);
2420 $useridto = $params['useridto'];
2421 $useridfrom = $params['useridfrom'];
2422 $type = $params['type'];
2423 $read = $params['read'];
2424 $newestfirst = $params['newestfirst'];
2425 $limitfrom = $params['limitfrom'];
2426 $limitnum = $params['limitnum'];
2428 $allowedvalues = array('notifications', 'conversations', 'both');
2429 if (!in_array($type, $allowedvalues)) {
2430 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
2431 'allowed values are: ' . implode(',', $allowedvalues));
2434 // Check if private messaging between users is allowed.
2435 if (empty($CFG->messaging)) {
2436 // If we are retreiving only conversations, and messaging is disabled, throw an exception.
2437 if ($type == "conversations") {
2438 throw new moodle_exception('disabled', 'message');
2440 if ($type == "both") {
2442 $warning['item'] = 'message';
2443 $warning['itemid'] = $USER->id;
2444 $warning['warningcode'] = '1';
2445 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
2446 Only notifications will be returned';
2447 $warnings[] = $warning;
2451 if (!empty($useridto)) {
2452 if (core_user::is_real_user($useridto)) {
2453 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2455 throw new moodle_exception('invaliduser');
2459 if (!empty($useridfrom)) {
2460 // We use get_user here because the from user can be the noreply or support user.
2461 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2464 // Check if the current user is the sender/receiver or just a privileged user.
2465 if ($useridto != $USER->id and $useridfrom != $USER->id and
2466 !has_capability('moodle/site:readallmessages', $context)) {
2467 throw new moodle_exception('accessdenied', 'admin');
2470 // Which type of messages to retrieve.
2471 $notifications = -1;
2472 if ($type != 'both') {
2473 $notifications = ($type == 'notifications') ? 1 : 0;
2476 $orderdirection = $newestfirst ? 'DESC' : 'ASC';
2477 $sort = "mr.timecreated $orderdirection";
2479 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
2480 $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
2482 // In some cases, we don't need to get the to/from user objects from the sql query.
2483 $userfromfullname = '';
2484 $usertofullname = '';
2486 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
2487 if (!empty($useridto)) {
2488 $usertofullname = fullname($userto, $canviewfullname);
2489 // The user from may or may not be filled.
2490 if (!empty($useridfrom)) {
2491 $userfromfullname = fullname($userfrom, $canviewfullname);
2494 // If the useridto field is empty, the useridfrom must be filled.
2495 $userfromfullname = fullname($userfrom, $canviewfullname);
2497 foreach ($messages as $mid => $message) {
2499 // Do not return deleted messages.
2500 if (!$message->notification) {
2501 if (($useridto == $USER->id and $message->timeusertodeleted) or
2502 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
2503 unset($messages[$mid]);
2508 // We need to get the user from the query.
2509 if (empty($userfromfullname)) {
2510 // Check for non-reply and support users.
2511 if (core_user::is_real_user($message->useridfrom)) {
2512 $user = new stdClass();
2513 $user = username_load_fields_from_object($user, $message, 'userfrom');
2514 $message->userfromfullname = fullname($user, $canviewfullname);
2516 $user = core_user::get_user($message->useridfrom);
2517 $message->userfromfullname = fullname($user, $canviewfullname);
2520 $message->userfromfullname = $userfromfullname;
2523 // We need to get the user from the query.
2524 if (empty($usertofullname)) {
2525 $user = new stdClass();
2526 $user = username_load_fields_from_object($user, $message, 'userto');
2527 $message->usertofullname = fullname($user, $canviewfullname);
2529 $message->usertofullname = $usertofullname;
2532 $message->text = message_format_message_text($message);
2533 $messages[$mid] = (array) $message;
2538 'messages' => $messages,
2539 'warnings' => $warnings
2546 * Get messages return description.
2548 * @return external_single_structure
2551 public static function get_messages_returns() {
2552 return new external_single_structure(
2554 'messages' => new external_multiple_structure(
2555 new external_single_structure(
2557 'id' => new external_value(PARAM_INT, 'Message id'),
2558 'useridfrom' => new external_value(PARAM_INT, 'User from id'),
2559 'useridto' => new external_value(PARAM_INT, 'User to id'),
2560 'subject' => new external_value(PARAM_TEXT, 'The message subject'),
2561 'text' => new external_value(PARAM_RAW, 'The message text formated'),
2562 'fullmessage' => new external_value(PARAM_RAW, 'The message'),
2563 'fullmessageformat' => new external_format_value('fullmessage'),
2564 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
2565 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
2566 'notification' => new external_value(PARAM_INT, 'Is a notification?'),
2567 'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
2568 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
2569 'timecreated' => new external_value(PARAM_INT, 'Time created'),
2570 'timeread' => new external_value(PARAM_INT, 'Time read'),
2571 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
2572 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
2576 'warnings' => new external_warnings()
2582 * Mark all notifications as read parameters description.
2584 * @return external_function_parameters
2587 public static function mark_all_notifications_as_read_parameters() {
2588 return new external_function_parameters(
2590 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2591 'useridfrom' => new external_value(
2592 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2599 * Mark all notifications as read function.
2602 * @throws invalid_parameter_exception
2603 * @throws moodle_exception
2604 * @param int $useridto the user id who received the message
2605 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2606 * @return external_description
2608 public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2611 $params = self::validate_parameters(
2612 self::mark_all_notifications_as_read_parameters(),
2614 'useridto' => $useridto,
2615 'useridfrom' => $useridfrom,
2619 $context = context_system::instance();
2620 self::validate_context($context);
2622 $useridto = $params['useridto'];
2623 $useridfrom = $params['useridfrom'];
2625 if (!empty($useridto)) {
2626 if (core_user::is_real_user($useridto)) {
2627 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2629 throw new moodle_exception('invaliduser');
2633 if (!empty($useridfrom)) {
2634 // We use get_user here because the from user can be the noreply or support user.
2635 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2638 // Check if the current user is the sender/receiver or just a privileged user.
2639 if ($useridto != $USER->id and $useridfrom != $USER->id and
2640 // The deleteanymessage cap seems more reasonable here than readallmessages.
2641 !has_capability('moodle/site:deleteanymessage', $context)) {
2642 throw new moodle_exception('accessdenied', 'admin');
2645 \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2651 * Mark all notifications as read return description.
2653 * @return external_single_structure
2656 public static function mark_all_notifications_as_read_returns() {
2657 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2661 * Get unread conversations count parameters description.
2663 * @return external_function_parameters
2666 public static function get_unread_conversations_count_parameters() {
2667 return new external_function_parameters(
2669 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2675 * Get unread messages count function.
2678 * @throws invalid_parameter_exception
2679 * @throws moodle_exception
2680 * @param int $useridto the user id who received the message
2681 * @return external_description
2683 public static function get_unread_conversations_count($useridto) {
2686 // Check if messaging is enabled.
2687 if (empty($CFG->messaging)) {
2688 throw new moodle_exception('disabled', 'message');
2691 $params = self::validate_parameters(
2692 self::get_unread_conversations_count_parameters(),
2693 array('useridto' => $useridto)
2696 $context = context_system::instance();
2697 self::validate_context($context);
2699 $useridto = $params['useridto'];
2701 if (!empty($useridto)) {
2702 if (core_user::is_real_user($useridto)) {
2703 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2705 throw new moodle_exception('invaliduser');
2708 $useridto = $USER->id;
2711 // Check if the current user is the receiver or just a privileged user.
2712 if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2713 throw new moodle_exception('accessdenied', 'admin');
2716 return \core_message\api::count_unread_conversations($userto);
2720 * Get unread conversations count return description.
2722 * @return external_single_structure
2725 public static function get_unread_conversations_count_returns() {
2726 return new external_value(PARAM_INT, 'The count of unread messages for the user');
2730 * Get blocked users parameters description.
2732 * @return external_function_parameters
2735 public static function get_blocked_users_parameters() {
2736 return new external_function_parameters(
2738 'userid' => new external_value(PARAM_INT,
2739 'the user whose blocked users we want to retrieve',
2746 * Retrieve a list of users blocked
2748 * @param int $userid the user whose blocked users we want to retrieve
2749 * @return external_description
2752 public static function get_blocked_users($userid) {
2753 global $CFG, $USER, $PAGE;
2755 // Warnings array, it can be empty at the end but is mandatory.
2756 $warnings = array();
2762 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
2763 $userid = $params['userid'];
2765 // Validate context.
2766 $context = context_system::instance();
2767 self::validate_context($context);
2769 // Check if private messaging between users is allowed.
2770 if (empty($CFG->messaging)) {
2771 throw new moodle_exception('disabled', 'message');
2774 $user = core_user::get_user($userid, '*', MUST_EXIST);
2775 core_user::require_active_user($user);
2777 // Check if we have permissions for retrieve the information.
2778 $capability = 'moodle/site:manageallmessaging';
2779 if (($USER->id != $userid) && !has_capability($capability, $context)) {
2780 throw new required_capability_exception($context, $capability, 'nopermissions', '');
2783 // Now, we can get safely all the blocked users.
2784 $users = \core_message\api::get_blocked_users($user->id);
2786 $blockedusers = array();
2787 foreach ($users as $user) {
2790 'fullname' => fullname($user),
2793 $userpicture = new user_picture($user);
2794 $userpicture->size = 1; // Size f1.
2795 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2797 $blockedusers[] = $newuser;
2801 'users' => $blockedusers,
2802 'warnings' => $warnings
2808 * Get blocked users return description.
2810 * @return external_single_structure
2813 public static function get_blocked_users_returns() {
2814 return new external_single_structure(
2816 'users' => new external_multiple_structure(
2817 new external_single_structure(
2819 'id' => new external_value(PARAM_INT, 'User ID'),
2820 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2821 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
2824 'List of blocked users'
2826 'warnings' => new external_warnings()
2832 * Returns description of method parameters
2834 * @return external_function_parameters
2837 public static function mark_message_read_parameters() {
2838 return new external_function_parameters(
2840 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
2841 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
2848 * Mark a single message as read, trigger message_viewed event
2850 * @param int $messageid id of the message (in the message table)
2851 * @param int $timeread timestamp for when the message should be marked read
2852 * @return external_description
2853 * @throws invalid_parameter_exception
2854 * @throws moodle_exception
2857 public static function mark_message_read($messageid, $timeread) {
2858 global $CFG, $DB, $USER;
2860 // Check if private messaging between users is allowed.
2861 if (empty($CFG->messaging)) {
2862 throw new moodle_exception('disabled', 'message');
2865 // Warnings array, it can be empty at the end but is mandatory.
2866 $warnings = array();
2870 'messageid' => $messageid,
2871 'timeread' => $timeread
2873 $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
2875 if (empty($params['timeread'])) {
2878 $timeread = $params['timeread'];
2881 // Validate context.
2882 $context = context_system::instance();
2883 self::validate_context($context);
2885 $sql = "SELECT m.*, mcm.userid as useridto
2887 INNER JOIN {message_conversations} mc
2888 ON m.conversationid = mc.id
2889 INNER JOIN {message_conversation_members} mcm
2890 ON mcm.conversationid = mc.id
2891 LEFT JOIN {message_user_actions} mua
2892 ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
2893 WHERE mua.id is NULL
2894 AND mcm.userid != m.useridfrom
2896 $messageparams = [];
2897 $messageparams[] = $USER->id;
2898 $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
2899 $messageparams[] = $params['messageid'];
2900 $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
2902 if ($message->useridto != $USER->id) {
2903 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
2906 \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
2909 'messageid' => $message->id,
2910 'warnings' => $warnings
2916 * Returns description of method result value
2918 * @return external_description
2921 public static function mark_message_read_returns() {
2922 return new external_single_structure(
2924 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
2925 'warnings' => new external_warnings()
2931 * Returns description of method parameters
2933 * @return external_function_parameters
2935 public static function mark_notification_read_parameters() {
2936 return new external_function_parameters(
2938 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2939 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
2946 * Mark a single notification as read.
2948 * This will trigger a 'notification_viewed' event.
2950 * @param int $notificationid id of the notification
2951 * @param int $timeread timestamp for when the notification should be marked read
2952 * @return external_description
2953 * @throws invalid_parameter_exception
2954 * @throws moodle_exception
2956 public static function mark_notification_read($notificationid, $timeread) {
2957 global $CFG, $DB, $USER;
2959 // Check if private messaging between users is allowed.
2960 if (empty($CFG->messaging)) {
2961 throw new moodle_exception('disabled', 'message');
2964 // Warnings array, it can be empty at the end but is mandatory.
2965 $warnings = array();
2969 'notificationid' => $notificationid,
2970 'timeread' => $timeread
2972 $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
2974 if (empty($params['timeread'])) {
2977 $timeread = $params['timeread'];
2980 // Validate context.
2981 $context = context_system::instance();
2982 self::validate_context($context);
2984 $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
2986 if ($notification->useridto != $USER->id) {
2987 throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
2988 'notification as read');
2991 \core_message\api::mark_notification_as_read($notification, $timeread);
2994 'notificationid' => $notification->id,
2995 'warnings' => $warnings
3002 * Returns description of method result value
3004 * @return external_description
3006 public static function mark_notification_read_returns() {
3007 return new external_single_structure(
3009 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3010 'warnings' => new external_warnings()
3016 * Mark all messages as read parameters description.
3018 * @deprecated since 3.6
3019 * @return external_function_parameters
3022 public static function mark_all_messages_as_read_parameters() {
3023 return new external_function_parameters(
3025 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3026 'useridfrom' => new external_value(
3027 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3034 * Mark all messages as read function.
3036 * @deprecated since 3.6
3037 * @throws invalid_parameter_exception
3038 * @throws moodle_exception
3039 * @param int $useridto the user id who received the message
3040 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
3041 * @return external_description
3044 public static function mark_all_messages_as_read($useridto, $useridfrom) {
3047 // Check if messaging is enabled.
3048 if (empty($CFG->messaging)) {
3049 throw new moodle_exception('disabled', 'message');
3052 $params = self::validate_parameters(
3053 self::mark_all_messages_as_read_parameters(),
3055 'useridto' => $useridto,
3056 'useridfrom' => $useridfrom,
3060 $context = context_system::instance();
3061 self::validate_context($context);
3063 $useridto = $params['useridto'];
3064 $useridfrom = $params['useridfrom'];
3066 if (!empty($useridto)) {
3067 if (core_user::is_real_user($useridto)) {
3068 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3070 throw new moodle_exception('invaliduser');
3074 if (!empty($useridfrom)) {
3075 // We use get_user here because the from user can be the noreply or support user.
3076 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3079 // Check if the current user is the sender/receiver or just a privileged user.
3080 if ($useridto != $USER->id and $useridfrom != $USER->id and
3081 // The deleteanymessage cap seems more reasonable here than readallmessages.
3082 !has_capability('moodle/site:deleteanymessage', $context)) {
3083 throw new moodle_exception('accessdenied', 'admin');
3087 if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
3088 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
3091 \core_message\api::mark_all_messages_as_read($useridto);
3098 * Mark all messages as read return description.
3100 * @deprecated since 3.6
3101 * @return external_single_structure
3104 public static function mark_all_messages_as_read_returns() {
3105 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
3109 * Marking the method as deprecated.
3113 public static function mark_all_messages_as_read_is_deprecated() {
3118 * Mark all conversation messages as read parameters description.
3120 * @return external_function_parameters
3123 public static function mark_all_conversation_messages_as_read_parameters() {
3124 return new external_function_parameters(
3126 'userid' => new external_value(PARAM_INT, 'The user id who who we are marking the messages as read for'),
3128 new external_value(PARAM_INT, 'The conversation id who who we are marking the messages as read for')
3134 * Mark all conversation messages as read function.
3136 * @param int $userid The user id of who we want to delete the conversation for
3137 * @param int $conversationid The id of the conversations
3140 public static function mark_all_conversation_messages_as_read(int $userid, int $conversationid) {
3143 // Check if messaging is enabled.
3144 if (empty($CFG->messaging)) {
3145 throw new moodle_exception('disabled', 'message');
3149 'userid' => $userid,
3150 'conversationid' => $conversationid,
3152 $params = self::validate_parameters(self::mark_all_conversation_messages_as_read_parameters(), $params);
3154 $context = context_system::instance();
3155 self::validate_context($context);
3157 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3158 core_user::require_active_user($user);
3160 if (\core_message\api::can_mark_all_messages_as_read($userid, $conversationid)) {
3161 \core_message\api::mark_all_messages_as_read($userid, $conversationid);
3163 throw new moodle_exception('accessdenied', 'admin');
3168 * Mark all conversation messages as read return description.
3170 * @return external_warnings
3173 public static function mark_all_conversation_messages_as_read_returns() {
3174 return new external_warnings();
3178 * Returns description of method parameters.
3180 * @deprecated since 3.6
3181 * @return external_function_parameters
3184 public static function delete_conversation_parameters() {
3185 return new external_function_parameters(
3187 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3188 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
3194 * Deletes a conversation.
3196 * @deprecated since 3.6
3197 * @param int $userid The user id of who we want to delete the conversation for
3198 * @param int $otheruserid The user id of the other user in the conversation
3200 * @throws moodle_exception
3203 public static function delete_conversation($userid, $otheruserid) {
3206 // Check if private messaging between users is allowed.
3207 if (empty($CFG->messaging)) {
3208 throw new moodle_exception('disabled', 'message');
3211 // Warnings array, it can be empty at the end but is mandatory.
3212 $warnings = array();
3216 'userid' => $userid,
3217 'otheruserid' => $otheruserid,
3219 $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
3221 // Validate context.
3222 $context = context_system::instance();
3223 self::validate_context($context);
3225 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3226 core_user::require_active_user($user);
3228 if (!$conversationid = \core_message\api::get_conversation_between_users([$userid, $otheruserid])) {
3232 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3233 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3236 throw new moodle_exception('You do not have permission to delete messages');
3240 'status' => $status,
3241 'warnings' => $warnings
3248 * Returns description of method result value.
3250 * @deprecated since 3.6
3251 * @return external_description
3254 public static function delete_conversation_returns() {
3255 return new external_single_structure(
3257 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
3258 'warnings' => new external_warnings()
3264 * Marking the method as deprecated.
3268 public static function delete_conversation_is_deprecated() {
3273 * Returns description of method parameters.
3275 * @return external_function_parameters
3278 public static function delete_conversations_by_id_parameters() {
3279 return new external_function_parameters(
3281 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3282 'conversationids' => new external_multiple_structure(
3283 new external_value(PARAM_INT, 'The id of the conversation'),
3284 'List of conversation IDs'
3291 * Deletes a conversation.
3293 * @param int $userid The user id of who we want to delete the conversation for
3294 * @param int[] $conversationids The ids of the conversations
3296 * @throws moodle_exception
3299 public static function delete_conversations_by_id($userid, array $conversationids) {
3302 // Check if private messaging between users is allowed.
3303 if (empty($CFG->messaging)) {
3304 throw new moodle_exception('disabled', 'message');
3309 'userid' => $userid,
3310 'conversationids' => $conversationids,
3312 $params = self::validate_parameters(self::delete_conversations_by_id_parameters(), $params);
3314 // Validate context.
3315 $context = context_system::instance();
3316 self::validate_context($context);
3318 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3319 core_user::require_active_user($user);
3321 foreach ($conversationids as $conversationid) {
3322 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3323 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3325 throw new moodle_exception("You do not have permission to delete the conversation '$conversationid'");
3333 * Returns description of method result value.
3335 * @return external_description
3338 public static function delete_conversations_by_id_returns() {
3339 return new external_warnings();
3343 * Returns description of method parameters
3345 * @return external_function_parameters
3348 public static function delete_message_parameters() {
3349 return new external_function_parameters(
3351 'messageid' => new external_value(PARAM_INT, 'The message id'),
3352 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
3353 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
3361 * @param int $messageid the message id
3362 * @param int $userid the user id of who we want to delete the message for
3363 * @param bool $read if is a message read (default to true)
3364 * @return external_description
3365 * @throws moodle_exception
3368 public static function delete_message($messageid, $userid, $read = true) {
3371 // Check if private messaging between users is allowed.
3372 if (empty($CFG->messaging)) {
3373 throw new moodle_exception('disabled', 'message');
3376 // Warnings array, it can be empty at the end but is mandatory.
3377 $warnings = array();
3381 'messageid' => $messageid,
3382 'userid' => $userid,
3385 $params = self::validate_parameters(self::delete_message_parameters(), $params);
3387 // Validate context.
3388 $context = context_system::instance();
3389 self::validate_context($context);
3391 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3392 core_user::require_active_user($user);
3394 if (\core_message\api::can_delete_message($user->id, $messageid)) {
3395 $status = \core_message\api::delete_message($user->id, $messageid);
3397 throw new moodle_exception('You do not have permission to delete this message');
3401 'status' => $status,
3402 'warnings' => $warnings
3408 * Returns description of method result value
3410 * @return external_description
3413 public static function delete_message_returns() {
3414 return new external_single_structure(
3416 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
3417 'warnings' => new external_warnings()
3423 * Returns description of method parameters
3425 * @return external_function_parameters
3428 public static function message_processor_config_form_parameters() {
3429 return new external_function_parameters(
3431 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
3432 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
3433 'formvalues' => new external_multiple_structure(
3434 new external_single_structure(