MDL-63303 message: fix get_conversations external func
[moodle.git] / message / externallib.php
blob07d01d580058ab2003aaed9e5ee70e023c10a645
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
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.
8 //
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/>.
18 /**
19 * External message API
21 * @package core_message
22 * @category external
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");
32 /**
33 * Message external functions
35 * @package core_message
36 * @category external
37 * @copyright 2011 Jerome Mouneyrac
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 * @since Moodle 2.2
41 class core_message_external extends external_api {
42 /**
43 * Returns description of method parameters
45 * @return external_function_parameters
46 * @since Moodle 3.6
48 public static function send_messages_to_conversation_parameters() {
49 return new external_function_parameters(
50 array(
51 'conversationid' => new external_value(PARAM_INT, 'id of the conversation'),
52 'messages' => new external_multiple_structure(
53 new external_single_structure(
54 array(
55 'text' => new external_value(PARAM_RAW, 'the text of the message'),
56 'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
64 /**
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).
72 * @since Moodle 3.6
74 public static function send_messages_to_conversation(int $conversationid, array $messages = []) {
75 global $CFG, $USER;
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
89 ]);
91 $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']);
97 return $messages;
101 * Returns description of method result value.
103 * @return external_description
104 * @since Moodle 3.6
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
117 * @since Moodle 2.2
119 public static function send_instant_messages_parameters() {
120 return new external_function_parameters(
121 array(
122 'messages' => new external_multiple_structure(
123 new external_single_structure(
124 array(
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.
140 * @return array
141 * @since Moodle 2.2
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 $messageids = array();
168 foreach ($params['messages'] as $message) {
169 $resultmsg = array(); //the infos about the success of the operation
171 // We are going to do some checking.
172 // Code should match /messages/index.php checks.
173 $success = true;
175 // Check the user exists.
176 if (empty($tousers[$message['touserid']])) {
177 $success = false;
178 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
181 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
182 // Check if the recipient can be messaged by the sender.
183 if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
184 $success = false;
185 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
188 // Now we can send the message (at least try).
189 if ($success) {
190 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
191 $success = message_post_message($USER, $tousers[$message['touserid']],
192 $message['text'], external_validate_format($message['textformat']));
195 // Build the resultmsg.
196 if (isset($message['clientmsgid'])) {
197 $resultmsg['clientmsgid'] = $message['clientmsgid'];
199 if ($success) {
200 $resultmsg['msgid'] = $success;
201 $resultmsg['text'] = message_format_message_text((object) [
202 'smallmessage' => $message['text'],
203 'fullmessageformat' => external_validate_format($message['textformat'])
205 $resultmsg['timecreated'] = time();
206 $messageids[] = $success;
207 } else {
208 // WARNINGS: for backward compatibility we return this errormessage.
209 // We should have thrown exceptions as these errors prevent results to be returned.
210 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
211 $resultmsg['msgid'] = -1;
212 $resultmsg['errormessage'] = $errormessage;
215 $resultmessages[] = $resultmsg;
218 if (!empty($messageids)) {
219 $messagerecords = $DB->get_records_list('messages', 'id', $messageids, '', 'id, conversationid');
220 $resultmessages = array_map(function($resultmessage) use ($messagerecords, $USER) {
221 $id = $resultmessage['msgid'];
222 $resultmessage['conversationid'] = isset($messagerecords[$id]) ? $messagerecords[$id]->conversationid : null;
223 $resultmessage['useridfrom'] = $USER->id;
224 return $resultmessage;
225 }, $resultmessages);
228 return $resultmessages;
232 * Returns description of method result value
234 * @return external_description
235 * @since Moodle 2.2
237 public static function send_instant_messages_returns() {
238 return new external_multiple_structure(
239 new external_single_structure(
240 array(
241 'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds: id of the created message if it succeeded, -1 when failed'),
242 'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
243 'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL),
244 'text' => new external_value(PARAM_RAW, 'The text of the message', VALUE_OPTIONAL),
245 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message', VALUE_OPTIONAL),
246 'conversationid' => new external_value(PARAM_INT, 'The conversation id for this message', VALUE_OPTIONAL),
247 'useridfrom' => new external_value(PARAM_INT, 'The user id who sent the message', VALUE_OPTIONAL),
254 * Create contacts parameters description.
256 * @deprecated since Moodle 3.6
257 * @return external_function_parameters
258 * @since Moodle 2.5
260 public static function create_contacts_parameters() {
261 return new external_function_parameters(
262 array(
263 'userids' => new external_multiple_structure(
264 new external_value(PARAM_INT, 'User ID'),
265 'List of user IDs'
267 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
268 current user', VALUE_DEFAULT, 0)
274 * Create contacts.
276 * @deprecated since Moodle 3.6
277 * @param array $userids array of user IDs.
278 * @param int $userid The id of the user we are creating the contacts for
279 * @return external_description
280 * @since Moodle 2.5
282 public static function create_contacts($userids, $userid = 0) {
283 global $CFG, $USER;
285 // Check if messaging is enabled.
286 if (empty($CFG->messaging)) {
287 throw new moodle_exception('disabled', 'message');
290 if (empty($userid)) {
291 $userid = $USER->id;
294 // Validate context.
295 $context = context_system::instance();
296 self::validate_context($context);
298 $params = array('userids' => $userids, 'userid' => $userid);
299 $params = self::validate_parameters(self::create_contacts_parameters(), $params);
301 $capability = 'moodle/site:manageallmessaging';
302 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
303 throw new required_capability_exception($context, $capability, 'nopermissions', '');
306 $warnings = array();
307 foreach ($params['userids'] as $id) {
308 if (!message_add_contact($id, 0, $params['userid'])) {
309 $warnings[] = array(
310 'item' => 'user',
311 'itemid' => $id,
312 'warningcode' => 'contactnotcreated',
313 'message' => 'The contact could not be created'
317 return $warnings;
321 * Create contacts return description.
323 * @deprecated since Moodle 3.6
324 * @return external_description
325 * @since Moodle 2.5
327 public static function create_contacts_returns() {
328 return new external_warnings();
332 * Marking the method as deprecated.
334 * @return bool
336 public static function create_contacts_is_deprecated() {
337 return true;
341 * Delete contacts parameters description.
343 * @return external_function_parameters
344 * @since Moodle 2.5
346 public static function delete_contacts_parameters() {
347 return new external_function_parameters(
348 array(
349 'userids' => new external_multiple_structure(
350 new external_value(PARAM_INT, 'User ID'),
351 'List of user IDs'
353 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
354 current user', VALUE_DEFAULT, 0)
360 * Delete contacts.
362 * @param array $userids array of user IDs.
363 * @param int $userid The id of the user we are deleting the contacts for
364 * @return null
365 * @since Moodle 2.5
367 public static function delete_contacts($userids, $userid = 0) {
368 global $CFG, $USER;
370 // Check if messaging is enabled.
371 if (empty($CFG->messaging)) {
372 throw new moodle_exception('disabled', 'message');
375 if (empty($userid)) {
376 $userid = $USER->id;
379 // Validate context.
380 $context = context_system::instance();
381 self::validate_context($context);
383 $params = array('userids' => $userids, 'userid' => $userid);
384 $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
386 $capability = 'moodle/site:manageallmessaging';
387 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
388 throw new required_capability_exception($context, $capability, 'nopermissions', '');
391 foreach ($params['userids'] as $id) {
392 \core_message\api::remove_contact($params['userid'], $id);
395 return null;
399 * Delete contacts return description.
401 * @return external_description
402 * @since Moodle 2.5
404 public static function delete_contacts_returns() {
405 return null;
409 * Block user parameters description.
411 * @return external_function_parameters
413 public static function block_user_parameters() {
414 return new external_function_parameters(
416 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
417 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
423 * Blocks a user.
425 * @param int $userid The id of the user who is blocking
426 * @param int $blockeduserid The id of the user being blocked
427 * @return external_description
429 public static function block_user(int $userid, int $blockeduserid) {
430 global $CFG, $USER;
432 // Check if messaging is enabled.
433 if (empty($CFG->messaging)) {
434 throw new moodle_exception('disabled', 'message');
437 // Validate context.
438 $context = context_system::instance();
439 self::validate_context($context);
441 $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
442 $params = self::validate_parameters(self::block_user_parameters(), $params);
444 $capability = 'moodle/site:manageallmessaging';
445 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
446 throw new required_capability_exception($context, $capability, 'nopermissions', '');
449 if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
450 \core_message\api::block_user($params['userid'], $params['blockeduserid']);
453 return [];
457 * Block user return description.
459 * @return external_description
461 public static function block_user_returns() {
462 return new external_warnings();
466 * Unblock user parameters description.
468 * @return external_function_parameters
470 public static function unblock_user_parameters() {
471 return new external_function_parameters(
473 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
474 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
480 * Unblock user.
482 * @param int $userid The id of the user who is unblocking
483 * @param int $unblockeduserid The id of the user being unblocked
485 public static function unblock_user(int $userid, int $unblockeduserid) {
486 global $CFG, $USER;
488 // Check if messaging is enabled.
489 if (empty($CFG->messaging)) {
490 throw new moodle_exception('disabled', 'message');
493 // Validate context.
494 $context = context_system::instance();
495 self::validate_context($context);
497 $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
498 $params = self::validate_parameters(self::unblock_user_parameters(), $params);
500 $capability = 'moodle/site:manageallmessaging';
501 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
502 throw new required_capability_exception($context, $capability, 'nopermissions', '');
505 \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
507 return [];
511 * Unblock user return description.
513 * @return external_description
515 public static function unblock_user_returns() {
516 return new external_warnings();
520 * Block contacts parameters description.
522 * @deprecated since Moodle 3.6
523 * @return external_function_parameters
524 * @since Moodle 2.5
526 public static function block_contacts_parameters() {
527 return new external_function_parameters(
528 array(
529 'userids' => new external_multiple_structure(
530 new external_value(PARAM_INT, 'User ID'),
531 'List of user IDs'
533 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
534 current user', VALUE_DEFAULT, 0)
540 * Block contacts.
542 * @deprecated since Moodle 3.6
543 * @param array $userids array of user IDs.
544 * @param int $userid The id of the user we are blocking the contacts for
545 * @return external_description
546 * @since Moodle 2.5
548 public static function block_contacts($userids, $userid = 0) {
549 global $CFG, $USER;
551 // Check if messaging is enabled.
552 if (empty($CFG->messaging)) {
553 throw new moodle_exception('disabled', 'message');
556 if (empty($userid)) {
557 $userid = $USER->id;
560 // Validate context.
561 $context = context_system::instance();
562 self::validate_context($context);
564 $params = array('userids' => $userids, 'userid' => $userid);
565 $params = self::validate_parameters(self::block_contacts_parameters(), $params);
567 $capability = 'moodle/site:manageallmessaging';
568 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
569 throw new required_capability_exception($context, $capability, 'nopermissions', '');
572 $warnings = array();
573 foreach ($params['userids'] as $id) {
574 if (!message_block_contact($id, $params['userid'])) {
575 $warnings[] = array(
576 'item' => 'user',
577 'itemid' => $id,
578 'warningcode' => 'contactnotblocked',
579 'message' => 'The contact could not be blocked'
583 return $warnings;
587 * Block contacts return description.
589 * @deprecated since Moodle 3.6
590 * @return external_description
591 * @since Moodle 2.5
593 public static function block_contacts_returns() {
594 return new external_warnings();
598 * Marking the method as deprecated.
600 * @return bool
602 public static function block_contacts_is_deprecated() {
603 return true;
607 * Unblock contacts parameters description.
609 * @deprecated since Moodle 3.6
610 * @return external_function_parameters
611 * @since Moodle 2.5
613 public static function unblock_contacts_parameters() {
614 return new external_function_parameters(
615 array(
616 'userids' => new external_multiple_structure(
617 new external_value(PARAM_INT, 'User ID'),
618 'List of user IDs'
620 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
621 current user', VALUE_DEFAULT, 0)
627 * Unblock contacts.
629 * @param array $userids array of user IDs.
630 * @param int $userid The id of the user we are unblocking the contacts for
631 * @return null
632 * @since Moodle 2.5
634 public static function unblock_contacts($userids, $userid = 0) {
635 global $CFG, $USER;
637 // Check if messaging is enabled.
638 if (empty($CFG->messaging)) {
639 throw new moodle_exception('disabled', 'message');
642 if (empty($userid)) {
643 $userid = $USER->id;
646 // Validate context.
647 $context = context_system::instance();
648 self::validate_context($context);
650 $params = array('userids' => $userids, 'userid' => $userid);
651 $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
653 $capability = 'moodle/site:manageallmessaging';
654 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
655 throw new required_capability_exception($context, $capability, 'nopermissions', '');
658 foreach ($params['userids'] as $id) {
659 message_unblock_contact($id, $params['userid']);
662 return null;
666 * Unblock contacts return description.
668 * @deprecated since Moodle 3.6
669 * @return external_description
670 * @since Moodle 2.5
672 public static function unblock_contacts_returns() {
673 return null;
677 * Marking the method as deprecated.
679 * @return bool
681 public static function unblock_contacts_is_deprecated() {
682 return true;
686 * Returns contact requests parameters description.
688 * @return external_function_parameters
690 public static function get_contact_requests_parameters() {
691 return new external_function_parameters(
693 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for'),
694 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
695 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
701 * Handles returning the contact requests for a user.
703 * This also includes the user data necessary to display information
704 * about the user.
706 * It will not include blocked users.
708 * @param int $userid The id of the user we want to get the contact requests for
709 * @param int $limitfrom
710 * @param int $limitnum
712 public static function get_contact_requests(int $userid, int $limitfrom = 0, int $limitnum = 0) {
713 global $CFG, $USER;
715 // Check if messaging is enabled.
716 if (empty($CFG->messaging)) {
717 throw new moodle_exception('disabled', 'message');
720 // Validate context.
721 $context = context_system::instance();
722 self::validate_context($context);
724 $params = [
725 'userid' => $userid,
726 'limitfrom' => $limitfrom,
727 'limitnum' => $limitnum
729 $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
731 $capability = 'moodle/site:manageallmessaging';
732 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
733 throw new required_capability_exception($context, $capability, 'nopermissions', '');
736 return \core_message\api::get_contact_requests($params['userid'], $params['limitfrom'], $params['limitnum']);
740 * Returns the contact requests return description.
742 * @return external_description
744 public static function get_contact_requests_returns() {
745 return new external_multiple_structure(
746 self::get_conversation_member_structure()
751 * Returns get conversation members parameters description.
753 * @return external_function_parameters
755 public static function get_conversation_members_parameters() {
756 return new external_function_parameters(
758 'userid' => new external_value(PARAM_INT, 'The id of the user we are performing this action on behalf of'),
759 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation'),
760 'includecontactrequests' => new external_value(PARAM_BOOL, 'Do we want to include contact requests?',
761 VALUE_DEFAULT, false),
762 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
763 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
769 * Returns a list of conversation members.
771 * @param int $userid The user we are returning the conversation members for, used by helper::get_member_info.
772 * @param int $conversationid The id of the conversation
773 * @param bool $includecontactrequests Do we want to include contact requests with this data?
774 * @param int $limitfrom
775 * @param int $limitnum
776 * @return array
778 public static function get_conversation_members(int $userid, int $conversationid, bool $includecontactrequests = false,
779 int $limitfrom = 0, int $limitnum = 0) {
780 global $CFG, $USER;
782 // Check if messaging is enabled.
783 if (empty($CFG->messaging)) {
784 throw new moodle_exception('disabled', 'message');
787 // Validate context.
788 $context = context_system::instance();
789 self::validate_context($context);
791 $params = [
792 'userid' => $userid,
793 'conversationid' => $conversationid,
794 'includecontactrequests' => $includecontactrequests,
795 'limitfrom' => $limitfrom,
796 'limitnum' => $limitnum
798 $params = self::validate_parameters(self::get_conversation_members_parameters(), $params);
800 $capability = 'moodle/site:manageallmessaging';
801 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
802 throw new required_capability_exception($context, $capability, 'nopermissions', '');
805 // The user needs to be a part of the conversation before querying who the members are.
806 if (!\core_message\api::is_user_in_conversation($params['userid'], $params['conversationid'])) {
807 throw new moodle_exception('You are not a member of this conversation.');
811 return \core_message\api::get_conversation_members($params['userid'], $params['conversationid'], $params['includecontactrequests'],
812 $params['limitfrom'], $params['limitnum']);
816 * Returns the get conversation members return description.
818 * @return external_description
820 public static function get_conversation_members_returns() {
821 return new external_multiple_structure(
822 self::get_conversation_member_structure(true)
827 * Creates a contact request parameters description.
829 * @return external_function_parameters
831 public static function create_contact_request_parameters() {
832 return new external_function_parameters(
834 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
835 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
841 * Creates a contact request.
843 * @param int $userid The id of the user who is creating the contact request
844 * @param int $requesteduserid The id of the user being requested
846 public static function create_contact_request(int $userid, int $requesteduserid) {
847 global $CFG, $USER;
849 // Check if messaging is enabled.
850 if (empty($CFG->messaging)) {
851 throw new moodle_exception('disabled', 'message');
854 // Validate context.
855 $context = context_system::instance();
856 self::validate_context($context);
858 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
859 $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
861 $capability = 'moodle/site:manageallmessaging';
862 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
863 throw new required_capability_exception($context, $capability, 'nopermissions', '');
866 $result = [
867 'warnings' => []
870 if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
871 $result['warnings'][] = [
872 'item' => 'user',
873 'itemid' => $params['requesteduserid'],
874 'warningcode' => 'cannotcreatecontactrequest',
875 'message' => 'You are unable to create a contact request for this user'
877 } else {
878 if ($requests = \core_message\api::get_contact_requests_between_users($params['userid'], $params['requesteduserid'])) {
879 // There should only ever be one but just in case there are multiple then we can return the first.
880 $result['request'] = array_shift($requests);
881 } else {
882 $result['request'] = \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
886 return $result;
890 * Creates a contact request return description.
892 * @return external_description
894 public static function create_contact_request_returns() {
895 return new external_single_structure(
896 array(
897 'request' => new external_single_structure(
898 array(
899 'id' => new external_value(PARAM_INT, 'Message id'),
900 'userid' => new external_value(PARAM_INT, 'User from id'),
901 'requesteduserid' => new external_value(PARAM_INT, 'User to id'),
902 'timecreated' => new external_value(PARAM_INT, 'Time created'),
904 'request record',
905 VALUE_OPTIONAL
907 'warnings' => new external_warnings()
913 * Confirm a contact request parameters description.
915 * @return external_function_parameters
917 public static function confirm_contact_request_parameters() {
918 return new external_function_parameters(
920 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
921 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
927 * Confirm a contact request.
929 * @param int $userid The id of the user who is creating the contact request
930 * @param int $requesteduserid The id of the user being requested
932 public static function confirm_contact_request(int $userid, int $requesteduserid) {
933 global $CFG, $USER;
935 // Check if messaging is enabled.
936 if (empty($CFG->messaging)) {
937 throw new moodle_exception('disabled', 'message');
940 // Validate context.
941 $context = context_system::instance();
942 self::validate_context($context);
944 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
945 $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
947 $capability = 'moodle/site:manageallmessaging';
948 if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
949 throw new required_capability_exception($context, $capability, 'nopermissions', '');
952 \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
954 return [];
958 * Confirm a contact request return description.
960 * @return external_description
962 public static function confirm_contact_request_returns() {
963 return new external_warnings();
967 * Declines a contact request parameters description.
969 * @return external_function_parameters
971 public static function decline_contact_request_parameters() {
972 return new external_function_parameters(
974 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
975 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
981 * Declines a contact request.
983 * @param int $userid The id of the user who is creating the contact request
984 * @param int $requesteduserid The id of the user being requested
986 public static function decline_contact_request(int $userid, int $requesteduserid) {
987 global $CFG, $USER;
989 // Check if messaging is enabled.
990 if (empty($CFG->messaging)) {
991 throw new moodle_exception('disabled', 'message');
994 // Validate context.
995 $context = context_system::instance();
996 self::validate_context($context);
998 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
999 $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
1001 $capability = 'moodle/site:manageallmessaging';
1002 if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
1003 throw new required_capability_exception($context, $capability, 'nopermissions', '');
1006 \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
1008 return [];
1012 * Declines a contact request return description.
1014 * @return external_description
1016 public static function decline_contact_request_returns() {
1017 return new external_warnings();
1021 * Return the structure of a message area contact.
1023 * @return external_single_structure
1024 * @since Moodle 3.2
1026 private static function get_messagearea_contact_structure() {
1027 return new external_single_structure(
1028 array(
1029 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
1030 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1031 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1032 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1033 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
1034 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
1035 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
1036 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
1037 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1038 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1039 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
1040 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1041 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1042 VALUE_DEFAULT, null),
1048 * Return the structure of a conversation.
1050 * @return external_single_structure
1051 * @since Moodle 3.6
1053 private static function get_conversation_structure() {
1054 return new external_single_structure(
1055 array(
1056 'id' => new external_value(PARAM_INT, 'The conversation id'),
1057 'name' => new external_value(PARAM_NOTAGS, 'The conversation name, if set', VALUE_DEFAULT, null),
1058 'subname' => new external_value(PARAM_NOTAGS, 'A subtitle for the conversation name, if set', VALUE_DEFAULT, null),
1059 'imageurl' => new external_value(PARAM_URL, 'A link to the conversation picture, if set', VALUE_DEFAULT, null),
1060 'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group)'),
1061 'membercount' => new external_value(PARAM_INT, 'Total number of conversation members'),
1062 'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked conversation this conversation as a favourite'),
1063 'isread' => new external_value(PARAM_BOOL, 'If the user has read all messages in the conversation'),
1064 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1065 VALUE_DEFAULT, null),
1066 'members' => new external_multiple_structure(
1067 self::get_conversation_member_structure(true)
1069 'messages' => new external_multiple_structure(
1070 self::get_conversation_message_structure()
1077 * Return the structure of a conversation member.
1079 * @param bool $includecontactrequests Are we including contact requests?
1080 * @param bool $includeconversations Are we including conversations?
1081 * @return external_single_structure
1082 * @since Moodle 3.6
1084 private static function get_conversation_member_structure(bool $includecontactrequests = false,
1085 bool $includeconversations = false) {
1086 $result = [
1087 'id' => new external_value(PARAM_INT, 'The user id'),
1088 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1089 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1090 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1091 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1092 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1093 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1094 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
1095 'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
1096 'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
1097 'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
1100 if ($includecontactrequests) {
1101 $result['contactrequests'] = new external_multiple_structure(
1102 new external_single_structure(
1104 'id' => new external_value(PARAM_INT, 'The id of the message'),
1105 'userid' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1106 'requesteduserid' => new external_value(PARAM_RAW, 'The text of the message'),
1107 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1109 ), 'The contact requests', VALUE_OPTIONAL
1113 if ($includeconversations) {
1114 $result['conversations'] = new external_multiple_structure(new external_single_structure(
1115 array(
1116 'id' => new external_value(PARAM_INT, 'Conversations id'),
1117 'type' => new external_value(PARAM_INT, 'Conversation type: private or public'),
1118 'name' => new external_value(PARAM_TEXT, 'Multilang compatible conversation name'. VALUE_OPTIONAL),
1119 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the conversation'),
1120 ), 'information about conversation', VALUE_OPTIONAL),
1121 'Conversations between users', VALUE_OPTIONAL
1125 return new external_single_structure(
1126 $result
1131 * Return the structure of a message area message.
1133 * @return external_single_structure
1134 * @since Moodle 3.6
1136 private static function get_conversation_message_structure() {
1137 return new external_single_structure(
1138 array(
1139 'id' => new external_value(PARAM_INT, 'The id of the message'),
1140 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1141 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1142 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1148 * Return the structure of a message area message.
1150 * @return external_single_structure
1151 * @since Moodle 3.2
1153 private static function get_messagearea_message_structure() {
1154 return new external_single_structure(
1155 array(
1156 'id' => new external_value(PARAM_INT, 'The id of the message'),
1157 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1158 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
1159 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1160 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
1161 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
1162 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
1163 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
1164 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1165 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
1171 * Get messagearea search users in course parameters.
1173 * @deprecated since 3.6
1175 * @return external_function_parameters
1176 * @since 3.2
1178 public static function data_for_messagearea_search_users_in_course_parameters() {
1179 return new external_function_parameters(
1180 array(
1181 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1182 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
1183 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1184 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1185 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1191 * Get messagearea search users in course results.
1193 * @deprecated since 3.6
1195 * NOTE: We are deprecating this function but not search_users_in_course API function for backwards compatibility
1196 * with messaging UI. But should be removed once new group messaging UI is in place and old messaging UI is removed.
1197 * Followup: MDL-63915
1199 * @param int $userid The id of the user who is performing the search
1200 * @param int $courseid The id of the course
1201 * @param string $search The string being searched
1202 * @param int $limitfrom
1203 * @param int $limitnum
1204 * @return stdClass
1205 * @throws moodle_exception
1206 * @since 3.2
1208 public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
1209 $limitnum = 0) {
1210 global $CFG, $PAGE, $USER;
1212 // Check if messaging is enabled.
1213 if (empty($CFG->messaging)) {
1214 throw new moodle_exception('disabled', 'message');
1217 $systemcontext = context_system::instance();
1219 $params = array(
1220 'userid' => $userid,
1221 'courseid' => $courseid,
1222 'search' => $search,
1223 'limitfrom' => $limitfrom,
1224 'limitnum' => $limitnum
1226 $params = self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
1227 self::validate_context($systemcontext);
1229 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1230 throw new moodle_exception('You do not have permission to perform this action.');
1233 $users = \core_message\api::search_users_in_course(
1234 $params['userid'],
1235 $params['courseid'],
1236 $params['search'],
1237 $params['limitfrom'],
1238 $params['limitnum']
1240 $results = new \core_message\output\messagearea\user_search_results($users);
1242 $renderer = $PAGE->get_renderer('core_message');
1243 return $results->export_for_template($renderer);
1247 * Get messagearea search users in course returns.
1249 * @deprecated since 3.6
1251 * @return external_single_structure
1252 * @since 3.2
1254 public static function data_for_messagearea_search_users_in_course_returns() {
1255 return new external_single_structure(
1256 array(
1257 'contacts' => new external_multiple_structure(
1258 self::get_messagearea_contact_structure()
1265 * Marking the method as deprecated.
1267 * @return bool
1269 public static function data_for_messagearea_search_users_in_course_is_deprecated() {
1270 return true;
1274 * Get messagearea search users parameters.
1276 * @deprecated since 3.6
1278 * @return external_function_parameters
1279 * @since 3.2
1281 public static function data_for_messagearea_search_users_parameters() {
1282 return new external_function_parameters(
1283 array(
1284 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1285 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1286 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1292 * Get messagearea search users results.
1294 * @deprecated since 3.6
1296 * NOTE: We are deprecating this function but not search_users API function for backwards compatibility
1297 * with messaging UI. But should be removed once new group messaging UI is in place and old messaging UI is removed.
1298 * Followup: MDL-63915
1300 * @param int $userid The id of the user who is performing the search
1301 * @param string $search The string being searched
1302 * @param int $limitnum
1303 * @return stdClass
1304 * @throws moodle_exception
1305 * @since 3.2
1307 public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1308 global $CFG, $PAGE, $USER;
1310 // Check if messaging is enabled.
1311 if (empty($CFG->messaging)) {
1312 throw new moodle_exception('disabled', 'message');
1315 $systemcontext = context_system::instance();
1317 $params = array(
1318 'userid' => $userid,
1319 'search' => $search,
1320 'limitnum' => $limitnum
1322 $params = self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1323 self::validate_context($systemcontext);
1325 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1326 throw new moodle_exception('You do not have permission to perform this action.');
1329 list($contacts, $courses, $noncontacts) = \core_message\api::search_users(
1330 $params['userid'],
1331 $params['search'],
1332 $params['limitnum']
1335 $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1337 $renderer = $PAGE->get_renderer('core_message');
1338 return $search->export_for_template($renderer);
1342 * Get messagearea search users returns.
1344 * @deprecated since 3.6
1346 * @return external_single_structure
1347 * @since 3.2
1349 public static function data_for_messagearea_search_users_returns() {
1350 return new external_single_structure(
1351 array(
1352 'contacts' => new external_multiple_structure(
1353 self::get_messagearea_contact_structure()
1355 'courses' => new external_multiple_structure(
1356 new external_single_structure(
1357 array(
1358 'id' => new external_value(PARAM_INT, 'The course id'),
1359 'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1360 'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1364 'noncontacts' => new external_multiple_structure(
1365 self::get_messagearea_contact_structure()
1372 * Marking the method as deprecated.
1374 * @return bool
1376 public static function data_for_messagearea_search_users_is_deprecated() {
1377 return true;
1381 * Get messagearea message search users parameters.
1383 * @return external_function_parameters
1384 * @since 3.6
1386 public static function message_search_users_parameters() {
1387 return new external_function_parameters(
1388 array(
1389 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1390 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1391 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1392 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1398 * Get search users results.
1400 * @param int $userid The id of the user who is performing the search
1401 * @param string $search The string being searched
1402 * @param int $limitfrom
1403 * @param int $limitnum
1404 * @return array
1405 * @throws moodle_exception
1406 * @since 3.6
1408 public static function message_search_users($userid, $search, $limitfrom = 0, $limitnum = 0) {
1409 global $USER;
1411 $systemcontext = context_system::instance();
1413 $params = array(
1414 'userid' => $userid,
1415 'search' => $search,
1416 'limitfrom' => $limitfrom,
1417 'limitnum' => $limitnum
1419 $params = self::validate_parameters(self::message_search_users_parameters(), $params);
1420 self::validate_context($systemcontext);
1422 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1423 throw new moodle_exception('You do not have permission to perform this action.');
1426 list($contacts, $noncontacts) = \core_message\api::message_search_users(
1427 $params['userid'],
1428 $params['search'],
1429 $params['limitfrom'],
1430 $params['limitnum']);
1432 return array('contacts' => $contacts, 'noncontacts' => $noncontacts);
1436 * Get messagearea message search users returns.
1438 * @return external_single_structure
1439 * @since 3.2
1441 public static function message_search_users_returns() {
1442 return new external_single_structure(
1443 array(
1444 'contacts' => new external_multiple_structure(
1445 self::get_conversation_member_structure(false, true)
1447 'noncontacts' => new external_multiple_structure(
1448 self::get_conversation_member_structure(false, true)
1455 * Get messagearea search messages parameters.
1457 * @return external_function_parameters
1458 * @since 3.2
1460 public static function data_for_messagearea_search_messages_parameters() {
1461 return new external_function_parameters(
1462 array(
1463 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1464 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1465 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1466 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1472 * Get messagearea search messages results.
1474 * @param int $userid The id of the user who is performing the search
1475 * @param string $search The string being searched
1476 * @param int $limitfrom
1477 * @param int $limitnum
1478 * @return stdClass
1479 * @throws moodle_exception
1480 * @since 3.2
1482 public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1483 global $CFG, $PAGE, $USER;
1485 // Check if messaging is enabled.
1486 if (empty($CFG->messaging)) {
1487 throw new moodle_exception('disabled', 'message');
1490 $systemcontext = context_system::instance();
1492 $params = array(
1493 'userid' => $userid,
1494 'search' => $search,
1495 'limitfrom' => $limitfrom,
1496 'limitnum' => $limitnum
1499 $params = self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1500 self::validate_context($systemcontext);
1502 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1503 throw new moodle_exception('You do not have permission to perform this action.');
1506 $messages = \core_message\api::search_messages(
1507 $params['userid'],
1508 $params['search'],
1509 $params['limitfrom'],
1510 $params['limitnum']
1512 $results = new \core_message\output\messagearea\message_search_results($messages);
1514 $renderer = $PAGE->get_renderer('core_message');
1515 return $results->export_for_template($renderer);
1519 * Get messagearea search messages returns.
1521 * @return external_single_structure
1522 * @since 3.2
1524 public static function data_for_messagearea_search_messages_returns() {
1525 return new external_single_structure(
1526 array(
1527 'contacts' => new external_multiple_structure(
1528 self::get_messagearea_contact_structure()
1535 * Get conversations parameters.
1537 * @return external_function_parameters
1538 * @since 3.6
1540 public static function get_conversations_parameters() {
1541 return new external_function_parameters(
1542 array(
1543 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1544 'limitfrom' => new external_value(PARAM_INT, 'The offset to start at', VALUE_DEFAULT, 0),
1545 'limitnum' => new external_value(PARAM_INT, 'Limit number of conversations to this', VALUE_DEFAULT, 0),
1546 'type' => new external_value(PARAM_INT, 'Filter by type', VALUE_DEFAULT, null),
1547 'favourites' => new external_value(PARAM_BOOL, 'Whether to restrict the results to contain NO favourite
1548 conversations (false), ONLY favourite conversation (true), or ignore any restriction altogether (null)',
1549 VALUE_DEFAULT, null),
1556 * Get the list of conversations for the user.
1558 * @param int $userid The id of the user who is performing the search
1559 * @param int $limitfrom
1560 * @param int $limitnum
1561 * @param int|null $type
1562 * @param bool|null $favourites
1563 * @return stdClass
1564 * @throws \moodle_exception if the messaging feature is disabled on the site.
1565 * @since 3.2
1567 public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null) {
1568 global $CFG, $USER;
1570 // All the standard BL checks.
1571 if (empty($CFG->messaging)) {
1572 throw new moodle_exception('disabled', 'message');
1575 $params = array(
1576 'userid' => $userid,
1577 'limitfrom' => $limitfrom,
1578 'limitnum' => $limitnum,
1579 'type' => $type,
1580 'favourites' => $favourites
1582 $params = self::validate_parameters(self::get_conversations_parameters(), $params);
1584 $systemcontext = context_system::instance();
1585 self::validate_context($systemcontext);
1587 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1588 throw new moodle_exception('You do not have permission to perform this action.');
1591 $conversations = \core_message\api::get_conversations(
1592 $params['userid'],
1593 $params['limitfrom'],
1594 $params['limitnum'],
1595 $params['type'],
1596 $params['favourites']
1599 return (object) ['conversations' => $conversations];
1603 * Get conversations returns.
1605 * @return external_single_structure
1606 * @since 3.6
1608 public static function get_conversations_returns() {
1609 return new external_single_structure(
1611 'conversations' => new external_multiple_structure(
1612 self::get_conversation_structure(true)
1619 * Get conversation parameters.
1621 * @return external_function_parameters
1623 public static function get_conversation_parameters() {
1624 return new external_function_parameters(
1625 array(
1626 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1627 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation to fetch'),
1628 'includecontactrequests' => new external_value(PARAM_BOOL, 'Include contact requests in the members'),
1629 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Include privacy info in the members'),
1630 'memberlimit' => new external_value(PARAM_INT, 'Limit for number of members', VALUE_DEFAULT, 0),
1631 'memberoffset' => new external_value(PARAM_INT, 'Offset for member list', VALUE_DEFAULT, 0),
1632 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
1633 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
1634 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
1640 * Get a single conversation.
1642 * @param int $userid The user id to get the conversation for
1643 * @param int $conversationid The id of the conversation to fetch
1644 * @param bool $includecontactrequests Should contact requests be included between members
1645 * @param bool $includeprivacyinfo Should privacy info be included between members
1646 * @param int $memberlimit Limit number of members to load
1647 * @param int $memberoffset Offset members by this amount
1648 * @param int $messagelimit Limit number of messages to load
1649 * @param int $messageoffset Offset the messages
1650 * @param bool $newestmessagesfirst Order messages by newest first
1651 * @return stdClass
1652 * @throws \moodle_exception if the messaging feature is disabled on the site.
1654 public static function get_conversation(
1655 int $userid,
1656 int $conversationid,
1657 bool $includecontactrequests = false,
1658 bool $includeprivacyinfo = false,
1659 int $memberlimit = 0,
1660 int $memberoffset = 0,
1661 int $messagelimit = 0,
1662 int $messageoffset = 0,
1663 bool $newestmessagesfirst = true
1665 global $CFG, $DB, $USER;
1667 // All the standard BL checks.
1668 if (empty($CFG->messaging)) {
1669 throw new moodle_exception('disabled', 'message');
1672 $params = [
1673 'userid' => $userid,
1674 'conversationid' => $conversationid,
1675 'includecontactrequests' => $includecontactrequests,
1676 'includeprivacyinfo' => $includeprivacyinfo,
1677 'memberlimit' => $memberlimit,
1678 'memberoffset' => $memberoffset,
1679 'messagelimit' => $messagelimit,
1680 'messageoffset' => $messageoffset,
1681 'newestmessagesfirst' => $newestmessagesfirst
1683 self::validate_parameters(self::get_conversation_parameters(), $params);
1685 $systemcontext = context_system::instance();
1686 self::validate_context($systemcontext);
1688 $conversation = \core_message\api::get_conversation(
1689 $params['userid'],
1690 $params['conversationid'],
1691 $params['includecontactrequests'],
1692 $params['includeprivacyinfo'],
1693 $params['memberlimit'],
1694 $params['memberoffset'],
1695 $params['messagelimit'],
1696 $params['messageoffset'],
1697 $params['newestmessagesfirst']
1700 if ($conversation) {
1701 return $conversation;
1702 } else {
1703 // We have to throw an exception here because the external functions annoyingly
1704 // don't accept null to be returned for a single structure.
1705 throw new \moodle_exception('Conversation does not exist');
1710 * Get conversation returns.
1712 * @return external_single_structure
1714 public static function get_conversation_returns() {
1715 return self::get_conversation_structure();
1719 * Get conversation parameters.
1721 * @return external_function_parameters
1723 public static function get_conversation_between_users_parameters() {
1724 return new external_function_parameters(
1725 array(
1726 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1727 'otheruserid' => new external_value(PARAM_INT, 'The other user id'),
1728 'includecontactrequests' => new external_value(PARAM_BOOL, 'Include contact requests in the members'),
1729 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Include privacy info in the members'),
1730 'memberlimit' => new external_value(PARAM_INT, 'Limit for number of members', VALUE_DEFAULT, 0),
1731 'memberoffset' => new external_value(PARAM_INT, 'Offset for member list', VALUE_DEFAULT, 0),
1732 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
1733 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
1734 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
1740 * Get a single conversation between users.
1742 * @param int $userid The user id to get the conversation for
1743 * @param int $otheruserid The other user id
1744 * @param bool $includecontactrequests Should contact requests be included between members
1745 * @param bool $includeprivacyinfo Should privacy info be included between members
1746 * @param int $memberlimit Limit number of members to load
1747 * @param int $memberoffset Offset members by this amount
1748 * @param int $messagelimit Limit number of messages to load
1749 * @param int $messageoffset Offset the messages
1750 * @param bool $newestmessagesfirst Order messages by newest first
1751 * @return stdClass
1752 * @throws \moodle_exception if the messaging feature is disabled on the site.
1754 public static function get_conversation_between_users(
1755 int $userid,
1756 int $otheruserid,
1757 bool $includecontactrequests = false,
1758 bool $includeprivacyinfo = false,
1759 int $memberlimit = 0,
1760 int $memberoffset = 0,
1761 int $messagelimit = 0,
1762 int $messageoffset = 0,
1763 bool $newestmessagesfirst = true
1765 global $CFG, $DB, $USER;
1767 // All the standard BL checks.
1768 if (empty($CFG->messaging)) {
1769 throw new moodle_exception('disabled', 'message');
1772 $params = [
1773 'userid' => $userid,
1774 'otheruserid' => $otheruserid,
1775 'includecontactrequests' => $includecontactrequests,
1776 'includeprivacyinfo' => $includeprivacyinfo,
1777 'memberlimit' => $memberlimit,
1778 'memberoffset' => $memberoffset,
1779 'messagelimit' => $messagelimit,
1780 'messageoffset' => $messageoffset,
1781 'newestmessagesfirst' => $newestmessagesfirst
1783 self::validate_parameters(self::get_conversation_between_users_parameters(), $params);
1785 $systemcontext = context_system::instance();
1786 self::validate_context($systemcontext);
1788 $conversationid = \core_message\api::get_conversation_between_users([$params['userid'], $params['otheruserid']]);
1789 $conversation = null;
1791 if ($conversationid) {
1792 $conversation = \core_message\api::get_conversation(
1793 $params['userid'],
1794 $conversationid,
1795 $params['includecontactrequests'],
1796 $params['includeprivacyinfo'],
1797 $params['memberlimit'],
1798 $params['memberoffset'],
1799 $params['messagelimit'],
1800 $params['messageoffset'],
1801 $params['newestmessagesfirst']
1805 if ($conversation) {
1806 return $conversation;
1807 } else {
1808 // We have to throw an exception here because the external functions annoyingly
1809 // don't accept null to be returned for a single structure.
1810 throw new \moodle_exception('Conversation does not exist');
1815 * Get conversation returns.
1817 * @return external_single_structure
1819 public static function get_conversation_between_users_returns() {
1820 return self::get_conversation_structure(true);
1824 * The messagearea conversations parameters.
1826 * @deprecated since 3.6
1827 * @return external_function_parameters
1828 * @since 3.2
1830 public static function data_for_messagearea_conversations_parameters() {
1831 return new external_function_parameters(
1832 array(
1833 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1834 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1835 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1841 * Get messagearea conversations.
1843 * NOTE FOR FINAL DEPRECATION:
1844 * When removing this method, please also consider removal of get_conversations_legacy_formatter()
1845 * from the \core_message\helper class. This helper method was used solely to format the new get_conversations() return data
1846 * into the old format used here, and in message/index.php. If we no longer need either of these, then that method can be
1847 * removed.
1849 * @deprecated since 3.6
1850 * @param int $userid The id of the user who we are viewing conversations for
1851 * @param int $limitfrom
1852 * @param int $limitnum
1853 * @return stdClass
1854 * @throws moodle_exception
1855 * @since 3.2
1857 public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1858 global $CFG, $PAGE, $USER;
1860 // Check if messaging is enabled.
1861 if (empty($CFG->messaging)) {
1862 throw new moodle_exception('disabled', 'message');
1865 $systemcontext = context_system::instance();
1867 $params = array(
1868 'userid' => $userid,
1869 'limitfrom' => $limitfrom,
1870 'limitnum' => $limitnum
1872 $params = self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1873 self::validate_context($systemcontext);
1875 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1876 throw new moodle_exception('You do not have permission to perform this action.');
1879 $conversations = \core_message\api::get_conversations($params['userid'], $params['limitfrom'], $params['limitnum']);
1881 // Format the conversations in the legacy style, as the get_conversations method has since been changed.
1882 $conversations = \core_message\helper::get_conversations_legacy_formatter($conversations);
1884 $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1886 $renderer = $PAGE->get_renderer('core_message');
1887 return $conversations->export_for_template($renderer);
1891 * The messagearea conversations return structure.
1893 * @deprecated since 3.6
1894 * @return external_single_structure
1895 * @since 3.2
1897 public static function data_for_messagearea_conversations_returns() {
1898 return new external_single_structure(
1899 array(
1900 'contacts' => new external_multiple_structure(
1901 self::get_messagearea_contact_structure()
1908 * Marking the method as deprecated.
1910 * @return bool
1912 public static function data_for_messagearea_conversations_is_deprecated() {
1913 return true;
1917 * The messagearea contacts return parameters.
1919 * @deprecated since 3.6
1920 * @return external_function_parameters
1921 * @since 3.2
1923 public static function data_for_messagearea_contacts_parameters() {
1924 return self::data_for_messagearea_conversations_parameters();
1928 * Get messagearea contacts parameters.
1930 * @deprecated since 3.6
1931 * @param int $userid The id of the user who we are viewing conversations for
1932 * @param int $limitfrom
1933 * @param int $limitnum
1934 * @return stdClass
1935 * @throws moodle_exception
1936 * @since 3.2
1938 public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1939 global $CFG, $PAGE, $USER;
1941 // Check if messaging is enabled.
1942 if (empty($CFG->messaging)) {
1943 throw new moodle_exception('disabled', 'message');
1946 $systemcontext = context_system::instance();
1948 $params = array(
1949 'userid' => $userid,
1950 'limitfrom' => $limitfrom,
1951 'limitnum' => $limitnum
1953 $params = self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1954 self::validate_context($systemcontext);
1956 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1957 throw new moodle_exception('You do not have permission to perform this action.');
1960 $contacts = \core_message\api::get_contacts($params['userid'], $params['limitfrom'], $params['limitnum']);
1961 $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1963 $renderer = $PAGE->get_renderer('core_message');
1964 return $contacts->export_for_template($renderer);
1968 * The messagearea contacts return structure.
1970 * @deprecated since 3.6
1971 * @return external_single_structure
1972 * @since 3.2
1974 public static function data_for_messagearea_contacts_returns() {
1975 return self::data_for_messagearea_conversations_returns();
1979 * Marking the method as deprecated.
1981 * @return bool
1983 public static function data_for_messagearea_contacts_is_deprecated() {
1984 return true;
1988 * The messagearea messages parameters.
1990 * @deprecated since 3.6
1991 * @return external_function_parameters
1992 * @since 3.2
1994 public static function data_for_messagearea_messages_parameters() {
1995 return new external_function_parameters(
1996 array(
1997 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1998 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1999 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2000 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
2001 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
2002 'timefrom' => new external_value(PARAM_INT,
2003 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
2009 * Get messagearea messages.
2011 * @deprecated since 3.6
2012 * @param int $currentuserid The current user's id
2013 * @param int $otheruserid The other user's id
2014 * @param int $limitfrom
2015 * @param int $limitnum
2016 * @param boolean $newest
2017 * @return stdClass
2018 * @throws moodle_exception
2019 * @since 3.2
2021 public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
2022 $newest = false, $timefrom = 0) {
2023 global $CFG, $PAGE, $USER;
2025 // Check if messaging is enabled.
2026 if (empty($CFG->messaging)) {
2027 throw new moodle_exception('disabled', 'message');
2030 $systemcontext = context_system::instance();
2032 $params = array(
2033 'currentuserid' => $currentuserid,
2034 'otheruserid' => $otheruserid,
2035 'limitfrom' => $limitfrom,
2036 'limitnum' => $limitnum,
2037 'newest' => $newest,
2038 'timefrom' => $timefrom,
2040 $params = self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
2041 self::validate_context($systemcontext);
2043 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2044 throw new moodle_exception('You do not have permission to perform this action.');
2047 if ($params['newest']) {
2048 $sort = 'timecreated DESC';
2049 } else {
2050 $sort = 'timecreated ASC';
2053 // We need to enforce a one second delay on messages to avoid race conditions of current
2054 // messages still being sent.
2056 // There is a chance that we could request messages before the current time's
2057 // second has elapsed and while other messages are being sent in that same second. In which
2058 // case those messages will be lost.
2060 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
2061 if (!empty($params['timefrom'])) {
2062 $timeto = time() - 1;
2063 } else {
2064 $timeto = 0;
2067 // No requesting messages from the current time, as stated above.
2068 if ($params['timefrom'] == time()) {
2069 $messages = [];
2070 } else {
2071 $messages = \core_message\api::get_messages($params['currentuserid'], $params['otheruserid'], $params['limitfrom'],
2072 $params['limitnum'], $sort, $params['timefrom'], $timeto);
2075 $messages = new \core_message\output\messagearea\messages($params['currentuserid'], $params['otheruserid'], $messages);
2077 $renderer = $PAGE->get_renderer('core_message');
2078 return $messages->export_for_template($renderer);
2082 * The messagearea messages return structure.
2084 * @deprecated since 3.6
2085 * @return external_single_structure
2086 * @since 3.2
2088 public static function data_for_messagearea_messages_returns() {
2089 return new external_single_structure(
2090 array(
2091 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
2092 the messages on behalf of?'),
2093 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2094 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2095 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
2096 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2097 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2098 'messages' => new external_multiple_structure(
2099 self::get_messagearea_message_structure()
2101 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
2107 * Marking the method as deprecated.
2109 * @return bool
2111 public static function data_for_messagearea_messages_is_deprecated() {
2112 return true;
2116 * The conversation messages parameters.
2118 * @return external_function_parameters
2119 * @since 3.6
2121 public static function get_conversation_messages_parameters() {
2122 return new external_function_parameters(
2123 array(
2124 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2125 'convid' => new external_value(PARAM_INT, 'The conversation id'),
2126 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2127 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
2128 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
2129 'timefrom' => new external_value(PARAM_INT,
2130 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
2136 * Get conversation messages.
2138 * @param int $currentuserid The current user's id.
2139 * @param int $convid The conversation id.
2140 * @param int $limitfrom Return a subset of records, starting at this point (optional).
2141 * @param int $limitnum Return a subset comprising this many records in total (optional, required if $limitfrom is set).
2142 * @param bool $newest True for getting first newest messages, false otherwise.
2143 * @param int $timefrom The time from the conversation messages to get.
2144 * @return stdClass The messages and members who have sent some of these messages.
2145 * @throws moodle_exception
2146 * @since 3.6
2148 public static function get_conversation_messages(int $currentuserid, int $convid, int $limitfrom = 0, int $limitnum = 0,
2149 bool $newest = false, int $timefrom = 0) {
2150 global $CFG, $PAGE, $USER;
2152 // Check if messaging is enabled.
2153 if (empty($CFG->messaging)) {
2154 throw new moodle_exception('disabled', 'message');
2157 $systemcontext = context_system::instance();
2159 $params = array(
2160 'currentuserid' => $currentuserid,
2161 'convid' => $convid,
2162 'limitfrom' => $limitfrom,
2163 'limitnum' => $limitnum,
2164 'newest' => $newest,
2165 'timefrom' => $timefrom,
2167 $params = self::validate_parameters(self::get_conversation_messages_parameters(), $params);
2168 self::validate_context($systemcontext);
2170 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2171 throw new moodle_exception('You do not have permission to perform this action.');
2174 $sort = $newest ? 'timecreated DESC' : 'timecreated ASC';
2176 // We need to enforce a one second delay on messages to avoid race conditions of current
2177 // messages still being sent.
2179 // There is a chance that we could request messages before the current time's
2180 // second has elapsed and while other messages are being sent in that same second. In which
2181 // case those messages will be lost.
2183 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
2184 $timeto = empty($params['timefrom']) ? 0 : time() - 1;
2186 // No requesting messages from the current time, as stated above.
2187 if ($params['timefrom'] == time()) {
2188 $messages = [];
2189 } else {
2190 $messages = \core_message\api::get_conversation_messages(
2191 $params['currentuserid'],
2192 $params['convid'],
2193 $params['limitfrom'],
2194 $params['limitnum'],
2195 $sort,
2196 $params['timefrom'],
2197 $timeto);
2200 return $messages;
2204 * The messagearea messages return structure.
2206 * @return external_single_structure
2207 * @since 3.6
2209 public static function get_conversation_messages_returns() {
2210 return new external_single_structure(
2211 array(
2212 'id' => new external_value(PARAM_INT, 'The conversation id'),
2213 'members' => new external_multiple_structure(
2214 self::get_conversation_member_structure()
2216 'messages' => new external_multiple_structure(
2217 self::get_conversation_message_structure()
2224 * The get most recent message return parameters.
2226 * @deprecated since 3.6
2227 * @return external_function_parameters
2228 * @since 3.2
2230 public static function data_for_messagearea_get_most_recent_message_parameters() {
2231 return new external_function_parameters(
2232 array(
2233 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2234 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2240 * Get the most recent message in a conversation.
2242 * @deprecated since 3.6
2243 * @param int $currentuserid The current user's id
2244 * @param int $otheruserid The other user's id
2245 * @return stdClass
2246 * @throws moodle_exception
2247 * @since 3.2
2249 public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
2250 global $CFG, $PAGE, $USER;
2252 // Check if messaging is enabled.
2253 if (empty($CFG->messaging)) {
2254 throw new moodle_exception('disabled', 'message');
2257 $systemcontext = context_system::instance();
2259 $params = array(
2260 'currentuserid' => $currentuserid,
2261 'otheruserid' => $otheruserid
2263 $params = self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
2264 self::validate_context($systemcontext);
2266 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2267 throw new moodle_exception('You do not have permission to perform this action.');
2270 $message = \core_message\api::get_most_recent_message($params['currentuserid'], $params['otheruserid']);
2271 $message = new \core_message\output\messagearea\message($message);
2273 $renderer = $PAGE->get_renderer('core_message');
2274 return $message->export_for_template($renderer);
2278 * The get most recent message return structure.
2280 * @deprecated since 3.6
2281 * @return external_single_structure
2282 * @since 3.2
2284 public static function data_for_messagearea_get_most_recent_message_returns() {
2285 return self::get_messagearea_message_structure();
2289 * Marking the method as deprecated.
2291 * @return bool
2293 public static function data_for_messagearea_get_most_recent_message_is_deprecated() {
2294 return true;
2298 * The get profile parameters.
2300 * @deprecated since 3.6
2301 * @return external_function_parameters
2302 * @since 3.2
2304 public static function data_for_messagearea_get_profile_parameters() {
2305 return new external_function_parameters(
2306 array(
2307 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2308 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
2314 * Get the profile information for a contact.
2316 * @deprecated since 3.6
2317 * @param int $currentuserid The current user's id
2318 * @param int $otheruserid The id of the user whose profile we are viewing
2319 * @return stdClass
2320 * @throws moodle_exception
2321 * @since 3.2
2323 public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
2324 global $CFG, $PAGE, $USER;
2326 // Check if messaging is enabled.
2327 if (empty($CFG->messaging)) {
2328 throw new moodle_exception('disabled', 'message');
2331 $systemcontext = context_system::instance();
2333 $params = array(
2334 'currentuserid' => $currentuserid,
2335 'otheruserid' => $otheruserid
2337 $params = self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
2338 self::validate_context($systemcontext);
2340 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2341 throw new moodle_exception('You do not have permission to perform this action.');
2344 $profile = \core_message\api::get_profile($params['currentuserid'], $params['otheruserid']);
2345 $profile = new \core_message\output\messagearea\profile($profile);
2347 $renderer = $PAGE->get_renderer('core_message');
2348 return $profile->export_for_template($renderer);
2352 * The get profile return structure.
2354 * @deprecated since 3.6
2355 * @return external_single_structure
2356 * @since 3.2
2358 public static function data_for_messagearea_get_profile_returns() {
2359 return new external_single_structure(
2360 array(
2361 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
2362 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
2363 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
2364 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
2365 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
2366 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
2367 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
2368 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2369 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2370 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
2371 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
2377 * Marking the method as deprecated.
2379 * @return bool
2381 public static function data_for_messagearea_get_profile_is_deprecated() {
2382 return true;
2386 * Get contacts parameters description.
2388 * @return external_function_parameters
2389 * @since Moodle 2.5
2391 public static function get_contacts_parameters() {
2392 return new external_function_parameters(array());
2396 * Get contacts.
2398 * @return external_description
2399 * @since Moodle 2.5
2401 public static function get_contacts() {
2402 global $CFG, $PAGE, $USER;
2404 // Check if messaging is enabled.
2405 if (empty($CFG->messaging)) {
2406 throw new moodle_exception('disabled', 'message');
2409 require_once($CFG->dirroot . '/user/lib.php');
2411 $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
2412 $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
2413 foreach ($contacts as $contact) {
2414 // Set the mode.
2415 $mode = 'offline';
2416 if (\core_message\helper::is_online($contact->lastaccess)) {
2417 $mode = 'online';
2420 $newcontact = array(
2421 'id' => $contact->id,
2422 'fullname' => fullname($contact),
2423 'unread' => $contact->messagecount
2426 $userpicture = new user_picture($contact);
2427 $userpicture->size = 1; // Size f1.
2428 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2429 $userpicture->size = 0; // Size f2.
2430 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2432 $allcontacts[$mode][$contact->id] = $newcontact;
2435 $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
2436 foreach ($strangers as $contact) {
2437 $newcontact = array(
2438 'id' => $contact->id,
2439 'fullname' => fullname($contact),
2440 'unread' => $contact->messagecount
2443 $userpicture = new user_picture($contact);
2444 $userpicture->size = 1; // Size f1.
2445 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2446 $userpicture->size = 0; // Size f2.
2447 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2449 $allcontacts['strangers'][$contact->id] = $newcontact;
2452 // Add noreply user and support user to the list, if they don't exist.
2453 $supportuser = core_user::get_support_user();
2454 if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
2455 $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
2456 if ($supportuser->messagecount > 0) {
2457 $supportuser->fullname = fullname($supportuser);
2458 $supportuser->unread = $supportuser->messagecount;
2459 $allcontacts['strangers'][$supportuser->id] = $supportuser;
2463 $noreplyuser = core_user::get_noreply_user();
2464 if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
2465 $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
2466 if ($noreplyuser->messagecount > 0) {
2467 $noreplyuser->fullname = fullname($noreplyuser);
2468 $noreplyuser->unread = $noreplyuser->messagecount;
2469 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
2473 return $allcontacts;
2477 * Get contacts return description.
2479 * @return external_description
2480 * @since Moodle 2.5
2482 public static function get_contacts_returns() {
2483 return new external_single_structure(
2484 array(
2485 'online' => new external_multiple_structure(
2486 new external_single_structure(
2487 array(
2488 'id' => new external_value(PARAM_INT, 'User ID'),
2489 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2490 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2491 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2492 'unread' => new external_value(PARAM_INT, 'Unread message count')
2495 'List of online contacts'
2497 'offline' => new external_multiple_structure(
2498 new external_single_structure(
2499 array(
2500 'id' => new external_value(PARAM_INT, 'User ID'),
2501 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2502 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2503 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2504 'unread' => new external_value(PARAM_INT, 'Unread message count')
2507 'List of offline contacts'
2509 'strangers' => new external_multiple_structure(
2510 new external_single_structure(
2511 array(
2512 'id' => new external_value(PARAM_INT, 'User ID'),
2513 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2514 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2515 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2516 'unread' => new external_value(PARAM_INT, 'Unread message count')
2519 'List of users that are not in the user\'s contact list but have sent a message'
2526 * Search contacts parameters description.
2528 * @return external_function_parameters
2529 * @since Moodle 2.5
2531 public static function search_contacts_parameters() {
2532 return new external_function_parameters(
2533 array(
2534 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
2535 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
2536 VALUE_DEFAULT, false)
2542 * Search contacts.
2544 * @param string $searchtext query string.
2545 * @param bool $onlymycourses limit the search to the user's courses only.
2546 * @return external_description
2547 * @since Moodle 2.5
2549 public static function search_contacts($searchtext, $onlymycourses = false) {
2550 global $CFG, $USER, $PAGE;
2551 require_once($CFG->dirroot . '/user/lib.php');
2553 // Check if messaging is enabled.
2554 if (empty($CFG->messaging)) {
2555 throw new moodle_exception('disabled', 'message');
2558 require_once($CFG->libdir . '/enrollib.php');
2560 $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
2561 $params = self::validate_parameters(self::search_contacts_parameters(), $params);
2563 // Extra validation, we do not allow empty queries.
2564 if ($params['searchtext'] === '') {
2565 throw new moodle_exception('querystringcannotbeempty');
2568 $courseids = array();
2569 if ($params['onlymycourses']) {
2570 $mycourses = enrol_get_my_courses(array('id'));
2571 foreach ($mycourses as $mycourse) {
2572 $courseids[] = $mycourse->id;
2574 } else {
2575 $courseids[] = SITEID;
2578 // Retrieving the users matching the query.
2579 $users = message_search_users($courseids, $params['searchtext']);
2580 $results = array();
2581 foreach ($users as $user) {
2582 $results[$user->id] = $user;
2585 // Reorganising information.
2586 foreach ($results as &$user) {
2587 $newuser = array(
2588 'id' => $user->id,
2589 'fullname' => fullname($user)
2592 // Avoid undefined property notice as phone not specified.
2593 $user->phone1 = null;
2594 $user->phone2 = null;
2596 $userpicture = new user_picture($user);
2597 $userpicture->size = 1; // Size f1.
2598 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2599 $userpicture->size = 0; // Size f2.
2600 $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2602 $user = $newuser;
2605 return $results;
2609 * Search contacts return description.
2611 * @return external_description
2612 * @since Moodle 2.5
2614 public static function search_contacts_returns() {
2615 return new external_multiple_structure(
2616 new external_single_structure(
2617 array(
2618 'id' => new external_value(PARAM_INT, 'User ID'),
2619 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2620 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2621 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
2624 'List of contacts'
2629 * Get messages parameters description.
2631 * @return external_function_parameters
2632 * @since 2.8
2634 public static function get_messages_parameters() {
2635 return new external_function_parameters(
2636 array(
2637 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2638 'useridfrom' => new external_value(
2639 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2640 VALUE_DEFAULT, 0),
2641 'type' => new external_value(
2642 PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
2643 VALUE_DEFAULT, 'both'),
2644 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
2645 'newestfirst' => new external_value(
2646 PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
2647 VALUE_DEFAULT, true),
2648 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
2649 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
2655 * Get messages function implementation.
2657 * @since 2.8
2658 * @throws invalid_parameter_exception
2659 * @throws moodle_exception
2660 * @param int $useridto the user id who received the message
2661 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2662 * @param string $type type of message to return, expected values: notifications, conversations and both
2663 * @param bool $read true for retreiving read messages, false for unread
2664 * @param bool $newestfirst true for ordering by newest first, false for oldest first
2665 * @param int $limitfrom limit from
2666 * @param int $limitnum limit num
2667 * @return external_description
2669 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
2670 $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
2671 global $CFG, $USER;
2673 $warnings = array();
2675 $params = array(
2676 'useridto' => $useridto,
2677 'useridfrom' => $useridfrom,
2678 'type' => $type,
2679 'read' => $read,
2680 'newestfirst' => $newestfirst,
2681 'limitfrom' => $limitfrom,
2682 'limitnum' => $limitnum
2685 $params = self::validate_parameters(self::get_messages_parameters(), $params);
2687 $context = context_system::instance();
2688 self::validate_context($context);
2690 $useridto = $params['useridto'];
2691 $useridfrom = $params['useridfrom'];
2692 $type = $params['type'];
2693 $read = $params['read'];
2694 $newestfirst = $params['newestfirst'];
2695 $limitfrom = $params['limitfrom'];
2696 $limitnum = $params['limitnum'];
2698 $allowedvalues = array('notifications', 'conversations', 'both');
2699 if (!in_array($type, $allowedvalues)) {
2700 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
2701 'allowed values are: ' . implode(',', $allowedvalues));
2704 // Check if private messaging between users is allowed.
2705 if (empty($CFG->messaging)) {
2706 // If we are retreiving only conversations, and messaging is disabled, throw an exception.
2707 if ($type == "conversations") {
2708 throw new moodle_exception('disabled', 'message');
2710 if ($type == "both") {
2711 $warning = array();
2712 $warning['item'] = 'message';
2713 $warning['itemid'] = $USER->id;
2714 $warning['warningcode'] = '1';
2715 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
2716 Only notifications will be returned';
2717 $warnings[] = $warning;
2721 if (!empty($useridto)) {
2722 if (core_user::is_real_user($useridto)) {
2723 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2724 } else {
2725 throw new moodle_exception('invaliduser');
2729 if (!empty($useridfrom)) {
2730 // We use get_user here because the from user can be the noreply or support user.
2731 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2734 // Check if the current user is the sender/receiver or just a privileged user.
2735 if ($useridto != $USER->id and $useridfrom != $USER->id and
2736 !has_capability('moodle/site:readallmessages', $context)) {
2737 throw new moodle_exception('accessdenied', 'admin');
2740 // Which type of messages to retrieve.
2741 $notifications = -1;
2742 if ($type != 'both') {
2743 $notifications = ($type == 'notifications') ? 1 : 0;
2746 $orderdirection = $newestfirst ? 'DESC' : 'ASC';
2747 $sort = "mr.timecreated $orderdirection";
2749 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
2750 $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
2752 // In some cases, we don't need to get the to/from user objects from the sql query.
2753 $userfromfullname = '';
2754 $usertofullname = '';
2756 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
2757 if (!empty($useridto)) {
2758 $usertofullname = fullname($userto, $canviewfullname);
2759 // The user from may or may not be filled.
2760 if (!empty($useridfrom)) {
2761 $userfromfullname = fullname($userfrom, $canviewfullname);
2763 } else {
2764 // If the useridto field is empty, the useridfrom must be filled.
2765 $userfromfullname = fullname($userfrom, $canviewfullname);
2767 foreach ($messages as $mid => $message) {
2769 // Do not return deleted messages.
2770 if (!$message->notification) {
2771 if (($useridto == $USER->id and $message->timeusertodeleted) or
2772 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
2773 unset($messages[$mid]);
2774 continue;
2778 // We need to get the user from the query.
2779 if (empty($userfromfullname)) {
2780 // Check for non-reply and support users.
2781 if (core_user::is_real_user($message->useridfrom)) {
2782 $user = new stdClass();
2783 $user = username_load_fields_from_object($user, $message, 'userfrom');
2784 $message->userfromfullname = fullname($user, $canviewfullname);
2785 } else {
2786 $user = core_user::get_user($message->useridfrom);
2787 $message->userfromfullname = fullname($user, $canviewfullname);
2789 } else {
2790 $message->userfromfullname = $userfromfullname;
2793 // We need to get the user from the query.
2794 if (empty($usertofullname)) {
2795 $user = new stdClass();
2796 $user = username_load_fields_from_object($user, $message, 'userto');
2797 $message->usertofullname = fullname($user, $canviewfullname);
2798 } else {
2799 $message->usertofullname = $usertofullname;
2802 $message->text = message_format_message_text($message);
2803 $messages[$mid] = (array) $message;
2807 $results = array(
2808 'messages' => $messages,
2809 'warnings' => $warnings
2812 return $results;
2816 * Get messages return description.
2818 * @return external_single_structure
2819 * @since 2.8
2821 public static function get_messages_returns() {
2822 return new external_single_structure(
2823 array(
2824 'messages' => new external_multiple_structure(
2825 new external_single_structure(
2826 array(
2827 'id' => new external_value(PARAM_INT, 'Message id'),
2828 'useridfrom' => new external_value(PARAM_INT, 'User from id'),
2829 'useridto' => new external_value(PARAM_INT, 'User to id'),
2830 'subject' => new external_value(PARAM_TEXT, 'The message subject'),
2831 'text' => new external_value(PARAM_RAW, 'The message text formated'),
2832 'fullmessage' => new external_value(PARAM_RAW, 'The message'),
2833 'fullmessageformat' => new external_format_value('fullmessage'),
2834 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
2835 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
2836 'notification' => new external_value(PARAM_INT, 'Is a notification?'),
2837 'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
2838 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
2839 'timecreated' => new external_value(PARAM_INT, 'Time created'),
2840 'timeread' => new external_value(PARAM_INT, 'Time read'),
2841 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
2842 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
2843 ), 'message'
2846 'warnings' => new external_warnings()
2852 * Mark all notifications as read parameters description.
2854 * @return external_function_parameters
2855 * @since 3.2
2857 public static function mark_all_notifications_as_read_parameters() {
2858 return new external_function_parameters(
2859 array(
2860 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2861 'useridfrom' => new external_value(
2862 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2863 VALUE_DEFAULT, 0),
2869 * Mark all notifications as read function.
2871 * @since 3.2
2872 * @throws invalid_parameter_exception
2873 * @throws moodle_exception
2874 * @param int $useridto the user id who received the message
2875 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2876 * @return external_description
2878 public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2879 global $USER;
2881 $params = self::validate_parameters(
2882 self::mark_all_notifications_as_read_parameters(),
2883 array(
2884 'useridto' => $useridto,
2885 'useridfrom' => $useridfrom,
2889 $context = context_system::instance();
2890 self::validate_context($context);
2892 $useridto = $params['useridto'];
2893 $useridfrom = $params['useridfrom'];
2895 if (!empty($useridto)) {
2896 if (core_user::is_real_user($useridto)) {
2897 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2898 } else {
2899 throw new moodle_exception('invaliduser');
2903 if (!empty($useridfrom)) {
2904 // We use get_user here because the from user can be the noreply or support user.
2905 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2908 // Check if the current user is the sender/receiver or just a privileged user.
2909 if ($useridto != $USER->id and $useridfrom != $USER->id and
2910 // The deleteanymessage cap seems more reasonable here than readallmessages.
2911 !has_capability('moodle/site:deleteanymessage', $context)) {
2912 throw new moodle_exception('accessdenied', 'admin');
2915 \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2917 return true;
2921 * Mark all notifications as read return description.
2923 * @return external_single_structure
2924 * @since 3.2
2926 public static function mark_all_notifications_as_read_returns() {
2927 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2931 * Get unread conversations count parameters description.
2933 * @return external_function_parameters
2934 * @since 3.2
2936 public static function get_unread_conversations_count_parameters() {
2937 return new external_function_parameters(
2938 array(
2939 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2945 * Get unread messages count function.
2947 * @since 3.2
2948 * @throws invalid_parameter_exception
2949 * @throws moodle_exception
2950 * @param int $useridto the user id who received the message
2951 * @return external_description
2953 public static function get_unread_conversations_count($useridto) {
2954 global $USER, $CFG;
2956 // Check if messaging is enabled.
2957 if (empty($CFG->messaging)) {
2958 throw new moodle_exception('disabled', 'message');
2961 $params = self::validate_parameters(
2962 self::get_unread_conversations_count_parameters(),
2963 array('useridto' => $useridto)
2966 $context = context_system::instance();
2967 self::validate_context($context);
2969 $useridto = $params['useridto'];
2971 if (!empty($useridto)) {
2972 if (core_user::is_real_user($useridto)) {
2973 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2974 } else {
2975 throw new moodle_exception('invaliduser');
2977 } else {
2978 $useridto = $USER->id;
2981 // Check if the current user is the receiver or just a privileged user.
2982 if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2983 throw new moodle_exception('accessdenied', 'admin');
2986 return \core_message\api::count_unread_conversations($userto);
2990 * Get unread conversations count return description.
2992 * @return external_single_structure
2993 * @since 3.2
2995 public static function get_unread_conversations_count_returns() {
2996 return new external_value(PARAM_INT, 'The count of unread messages for the user');
3000 * Get blocked users parameters description.
3002 * @return external_function_parameters
3003 * @since 2.9
3005 public static function get_blocked_users_parameters() {
3006 return new external_function_parameters(
3007 array(
3008 'userid' => new external_value(PARAM_INT,
3009 'the user whose blocked users we want to retrieve',
3010 VALUE_REQUIRED),
3016 * Retrieve a list of users blocked
3018 * @param int $userid the user whose blocked users we want to retrieve
3019 * @return external_description
3020 * @since 2.9
3022 public static function get_blocked_users($userid) {
3023 global $CFG, $USER, $PAGE;
3025 // Warnings array, it can be empty at the end but is mandatory.
3026 $warnings = array();
3028 // Validate params.
3029 $params = array(
3030 'userid' => $userid
3032 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
3033 $userid = $params['userid'];
3035 // Validate context.
3036 $context = context_system::instance();
3037 self::validate_context($context);
3039 // Check if private messaging between users is allowed.
3040 if (empty($CFG->messaging)) {
3041 throw new moodle_exception('disabled', 'message');
3044 $user = core_user::get_user($userid, '*', MUST_EXIST);
3045 core_user::require_active_user($user);
3047 // Check if we have permissions for retrieve the information.
3048 $capability = 'moodle/site:manageallmessaging';
3049 if (($USER->id != $userid) && !has_capability($capability, $context)) {
3050 throw new required_capability_exception($context, $capability, 'nopermissions', '');
3053 // Now, we can get safely all the blocked users.
3054 $users = \core_message\api::get_blocked_users($user->id);
3056 $blockedusers = array();
3057 foreach ($users as $user) {
3058 $newuser = array(
3059 'id' => $user->id,
3060 'fullname' => fullname($user),
3063 $userpicture = new user_picture($user);
3064 $userpicture->size = 1; // Size f1.
3065 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
3067 $blockedusers[] = $newuser;
3070 $results = array(
3071 'users' => $blockedusers,
3072 'warnings' => $warnings
3074 return $results;
3078 * Get blocked users return description.
3080 * @return external_single_structure
3081 * @since 2.9
3083 public static function get_blocked_users_returns() {
3084 return new external_single_structure(
3085 array(
3086 'users' => new external_multiple_structure(
3087 new external_single_structure(
3088 array(
3089 'id' => new external_value(PARAM_INT, 'User ID'),
3090 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
3091 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
3094 'List of blocked users'
3096 'warnings' => new external_warnings()
3102 * Returns description of method parameters
3104 * @return external_function_parameters
3105 * @since 2.9
3107 public static function mark_message_read_parameters() {
3108 return new external_function_parameters(
3109 array(
3110 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
3111 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
3112 VALUE_DEFAULT, 0)
3118 * Mark a single message as read, trigger message_viewed event
3120 * @param int $messageid id of the message (in the message table)
3121 * @param int $timeread timestamp for when the message should be marked read
3122 * @return external_description
3123 * @throws invalid_parameter_exception
3124 * @throws moodle_exception
3125 * @since 2.9
3127 public static function mark_message_read($messageid, $timeread) {
3128 global $CFG, $DB, $USER;
3130 // Check if private messaging between users is allowed.
3131 if (empty($CFG->messaging)) {
3132 throw new moodle_exception('disabled', 'message');
3135 // Warnings array, it can be empty at the end but is mandatory.
3136 $warnings = array();
3138 // Validate params.
3139 $params = array(
3140 'messageid' => $messageid,
3141 'timeread' => $timeread
3143 $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
3145 if (empty($params['timeread'])) {
3146 $timeread = time();
3147 } else {
3148 $timeread = $params['timeread'];
3151 // Validate context.
3152 $context = context_system::instance();
3153 self::validate_context($context);
3155 $sql = "SELECT m.*, mcm.userid as useridto
3156 FROM {messages} m
3157 INNER JOIN {message_conversations} mc
3158 ON m.conversationid = mc.id
3159 INNER JOIN {message_conversation_members} mcm
3160 ON mcm.conversationid = mc.id
3161 LEFT JOIN {message_user_actions} mua
3162 ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
3163 WHERE mua.id is NULL
3164 AND mcm.userid != m.useridfrom
3165 AND m.id = ?";
3166 $messageparams = [];
3167 $messageparams[] = $USER->id;
3168 $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
3169 $messageparams[] = $params['messageid'];
3170 $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
3172 if ($message->useridto != $USER->id) {
3173 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
3176 \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
3178 $results = array(
3179 'messageid' => $message->id,
3180 'warnings' => $warnings
3182 return $results;
3186 * Returns description of method result value
3188 * @return external_description
3189 * @since 2.9
3191 public static function mark_message_read_returns() {
3192 return new external_single_structure(
3193 array(
3194 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
3195 'warnings' => new external_warnings()
3201 * Returns description of method parameters
3203 * @return external_function_parameters
3205 public static function mark_notification_read_parameters() {
3206 return new external_function_parameters(
3207 array(
3208 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3209 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
3210 VALUE_DEFAULT, 0)
3216 * Mark a single notification as read.
3218 * This will trigger a 'notification_viewed' event.
3220 * @param int $notificationid id of the notification
3221 * @param int $timeread timestamp for when the notification should be marked read
3222 * @return external_description
3223 * @throws invalid_parameter_exception
3224 * @throws moodle_exception
3226 public static function mark_notification_read($notificationid, $timeread) {
3227 global $CFG, $DB, $USER;
3229 // Check if private messaging between users is allowed.
3230 if (empty($CFG->messaging)) {
3231 throw new moodle_exception('disabled', 'message');
3234 // Warnings array, it can be empty at the end but is mandatory.
3235 $warnings = array();
3237 // Validate params.
3238 $params = array(
3239 'notificationid' => $notificationid,
3240 'timeread' => $timeread
3242 $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
3244 if (empty($params['timeread'])) {
3245 $timeread = time();
3246 } else {
3247 $timeread = $params['timeread'];
3250 // Validate context.
3251 $context = context_system::instance();
3252 self::validate_context($context);
3254 $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
3256 if ($notification->useridto != $USER->id) {
3257 throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
3258 'notification as read');
3261 \core_message\api::mark_notification_as_read($notification, $timeread);
3263 $results = array(
3264 'notificationid' => $notification->id,
3265 'warnings' => $warnings
3268 return $results;
3272 * Returns description of method result value
3274 * @return external_description
3276 public static function mark_notification_read_returns() {
3277 return new external_single_structure(
3278 array(
3279 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3280 'warnings' => new external_warnings()
3286 * Mark all messages as read parameters description.
3288 * @deprecated since 3.6
3289 * @return external_function_parameters
3290 * @since 3.2
3292 public static function mark_all_messages_as_read_parameters() {
3293 return new external_function_parameters(
3294 array(
3295 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3296 'useridfrom' => new external_value(
3297 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3298 VALUE_DEFAULT, 0),
3304 * Mark all messages as read function.
3306 * @deprecated since 3.6
3307 * @throws invalid_parameter_exception
3308 * @throws moodle_exception
3309 * @param int $useridto the user id who received the message
3310 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
3311 * @return external_description
3312 * @since 3.2
3314 public static function mark_all_messages_as_read($useridto, $useridfrom) {
3315 global $USER, $CFG;
3317 // Check if messaging is enabled.
3318 if (empty($CFG->messaging)) {
3319 throw new moodle_exception('disabled', 'message');
3322 $params = self::validate_parameters(
3323 self::mark_all_messages_as_read_parameters(),
3324 array(
3325 'useridto' => $useridto,
3326 'useridfrom' => $useridfrom,
3330 $context = context_system::instance();
3331 self::validate_context($context);
3333 $useridto = $params['useridto'];
3334 $useridfrom = $params['useridfrom'];
3336 if (!empty($useridto)) {
3337 if (core_user::is_real_user($useridto)) {
3338 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3339 } else {
3340 throw new moodle_exception('invaliduser');
3344 if (!empty($useridfrom)) {
3345 // We use get_user here because the from user can be the noreply or support user.
3346 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3349 // Check if the current user is the sender/receiver or just a privileged user.
3350 if ($useridto != $USER->id and $useridfrom != $USER->id and
3351 // The deleteanymessage cap seems more reasonable here than readallmessages.
3352 !has_capability('moodle/site:deleteanymessage', $context)) {
3353 throw new moodle_exception('accessdenied', 'admin');
3356 if ($useridfrom) {
3357 if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
3358 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
3360 } else {
3361 \core_message\api::mark_all_messages_as_read($useridto);
3364 return true;
3368 * Mark all messages as read return description.
3370 * @deprecated since 3.6
3371 * @return external_single_structure
3372 * @since 3.2
3374 public static function mark_all_messages_as_read_returns() {
3375 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
3379 * Marking the method as deprecated.
3381 * @return bool
3383 public static function mark_all_messages_as_read_is_deprecated() {
3384 return true;
3388 * Mark all conversation messages as read parameters description.
3390 * @return external_function_parameters
3391 * @since 3.6
3393 public static function mark_all_conversation_messages_as_read_parameters() {
3394 return new external_function_parameters(
3395 array(
3396 'userid' => new external_value(PARAM_INT, 'The user id who who we are marking the messages as read for'),
3397 'conversationid' =>
3398 new external_value(PARAM_INT, 'The conversation id who who we are marking the messages as read for')
3404 * Mark all conversation messages as read function.
3406 * @param int $userid The user id of who we want to delete the conversation for
3407 * @param int $conversationid The id of the conversations
3408 * @since 3.6
3410 public static function mark_all_conversation_messages_as_read(int $userid, int $conversationid) {
3411 global $CFG;
3413 // Check if messaging is enabled.
3414 if (empty($CFG->messaging)) {
3415 throw new moodle_exception('disabled', 'message');
3418 $params = array(
3419 'userid' => $userid,
3420 'conversationid' => $conversationid,
3422 $params = self::validate_parameters(self::mark_all_conversation_messages_as_read_parameters(), $params);
3424 $context = context_system::instance();
3425 self::validate_context($context);
3427 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3428 core_user::require_active_user($user);
3430 if (\core_message\api::can_mark_all_messages_as_read($params['userid'], $params['conversationid'])) {
3431 \core_message\api::mark_all_messages_as_read($params['userid'], $params['conversationid']);
3432 } else {
3433 throw new moodle_exception('accessdenied', 'admin');
3438 * Mark all conversation messages as read return description.
3440 * @return external_warnings
3441 * @since 3.6
3443 public static function mark_all_conversation_messages_as_read_returns() {
3444 return null;
3448 * Returns description of method parameters.
3450 * @deprecated since 3.6
3451 * @return external_function_parameters
3452 * @since 3.2
3454 public static function delete_conversation_parameters() {
3455 return new external_function_parameters(
3456 array(
3457 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3458 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
3464 * Deletes a conversation.
3466 * @deprecated since 3.6
3467 * @param int $userid The user id of who we want to delete the conversation for
3468 * @param int $otheruserid The user id of the other user in the conversation
3469 * @return array
3470 * @throws moodle_exception
3471 * @since 3.2
3473 public static function delete_conversation($userid, $otheruserid) {
3474 global $CFG;
3476 // Check if private messaging between users is allowed.
3477 if (empty($CFG->messaging)) {
3478 throw new moodle_exception('disabled', 'message');
3481 // Warnings array, it can be empty at the end but is mandatory.
3482 $warnings = array();
3484 // Validate params.
3485 $params = array(
3486 'userid' => $userid,
3487 'otheruserid' => $otheruserid,
3489 $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
3491 // Validate context.
3492 $context = context_system::instance();
3493 self::validate_context($context);
3495 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3496 core_user::require_active_user($user);
3498 if (!$conversationid = \core_message\api::get_conversation_between_users([$params['userid'], $params['otheruserid']])) {
3499 return [];
3502 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3503 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3504 $status = true;
3505 } else {
3506 throw new moodle_exception('You do not have permission to delete messages');
3509 $results = array(
3510 'status' => $status,
3511 'warnings' => $warnings
3514 return $results;
3518 * Returns description of method result value.
3520 * @deprecated since 3.6
3521 * @return external_description
3522 * @since 3.2
3524 public static function delete_conversation_returns() {
3525 return new external_single_structure(
3526 array(
3527 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
3528 'warnings' => new external_warnings()
3534 * Marking the method as deprecated.
3536 * @return bool
3538 public static function delete_conversation_is_deprecated() {
3539 return true;
3543 * Returns description of method parameters.
3545 * @return external_function_parameters
3546 * @since 3.6
3548 public static function delete_conversations_by_id_parameters() {
3549 return new external_function_parameters(
3550 array(
3551 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3552 'conversationids' => new external_multiple_structure(
3553 new external_value(PARAM_INT, 'The id of the conversation'),
3554 'List of conversation IDs'
3561 * Deletes a conversation.
3563 * @param int $userid The user id of who we want to delete the conversation for
3564 * @param int[] $conversationids The ids of the conversations
3565 * @return array
3566 * @throws moodle_exception
3567 * @since 3.6
3569 public static function delete_conversations_by_id($userid, array $conversationids) {
3570 global $CFG;
3572 // Check if private messaging between users is allowed.
3573 if (empty($CFG->messaging)) {
3574 throw new moodle_exception('disabled', 'message');
3577 // Validate params.
3578 $params = [
3579 'userid' => $userid,
3580 'conversationids' => $conversationids,
3582 $params = self::validate_parameters(self::delete_conversations_by_id_parameters(), $params);
3584 // Validate context.
3585 $context = context_system::instance();
3586 self::validate_context($context);
3588 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3589 core_user::require_active_user($user);
3591 foreach ($params['conversationids'] as $conversationid) {
3592 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3593 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3594 } else {
3595 throw new moodle_exception("You do not have permission to delete the conversation '$conversationid'");
3599 return [];
3603 * Returns description of method result value.
3605 * @return external_description
3606 * @since 3.6
3608 public static function delete_conversations_by_id_returns() {
3609 return new external_warnings();
3613 * Returns description of method parameters
3615 * @return external_function_parameters
3616 * @since 3.1
3618 public static function delete_message_parameters() {
3619 return new external_function_parameters(
3620 array(
3621 'messageid' => new external_value(PARAM_INT, 'The message id'),
3622 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
3623 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
3629 * Deletes a message
3631 * @param int $messageid the message id
3632 * @param int $userid the user id of who we want to delete the message for
3633 * @param bool $read if is a message read (default to true)
3634 * @return external_description
3635 * @throws moodle_exception
3636 * @since 3.1
3638 public static function delete_message($messageid, $userid, $read = true) {
3639 global $CFG;
3641 // Check if private messaging between users is allowed.
3642 if (empty($CFG->messaging)) {
3643 throw new moodle_exception('disabled', 'message');
3646 // Warnings array, it can be empty at the end but is mandatory.
3647 $warnings = array();
3649 // Validate params.
3650 $params = array(
3651 'messageid' => $messageid,
3652 'userid' => $userid,
3653 'read' => $read
3655 $params = self::validate_parameters(self::delete_message_parameters(), $params);
3657 // Validate context.
3658 $context = context_system::instance();
3659 self::validate_context($context);
3661 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3662 core_user::require_active_user($user);
3664 if (\core_message\api::can_delete_message($user->id, $params['messageid'])) {
3665 $status = \core_message\api::delete_message($user->id, $params['messageid']);
3666 } else {
3667 throw new moodle_exception('You do not have permission to delete this message');
3670 $results = array(
3671 'status' => $status,
3672 'warnings' => $warnings
3674 return $results;
3678 * Returns description of method result value
3680 * @return external_description
3681 * @since 3.1
3683 public static function delete_message_returns() {
3684 return new external_single_structure(
3685 array(
3686 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
3687 'warnings' => new external_warnings()
3693 * Returns description of method parameters
3695 * @return external_function_parameters
3696 * @since 3.2
3698 public static function message_processor_config_form_parameters() {
3699 return new external_function_parameters(
3700 array(
3701 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
3702 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
3703 'formvalues' => new external_multiple_structure(
3704 new external_single_structure(
3705 array(
3706 'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
3707 'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
3710 'Config form values',
3711 VALUE_REQUIRED
3718 * Processes a message processor config form.
3720 * @param int $userid the user id
3721 * @param string $name the name of the processor
3722 * @param array $formvalues the form values
3723 * @return external_description
3724 * @throws moodle_exception
3725 * @since 3.2
3727 public static function message_processor_config_form($userid, $name, $formvalues) {
3728 global $USER, $CFG;
3730 // Check if messaging is enabled.
3731 if (empty($CFG->messaging)) {
3732 throw new moodle_exception('disabled', 'message');
3735 $params = self::validate_parameters(
3736 self::message_processor_config_form_parameters(),
3737 array(
3738 'userid' => $userid,
3739 'name' => $name,
3740 'formvalues' => $formvalues,
3744 $user = self::validate_preferences_permissions($params['userid']);
3746 $processor = get_message_processor($params['name']);
3747 $preferences = [];
3748 $form = new stdClass();
3750 foreach ($params['formvalues'] as $formvalue) {
3751 // Curly braces to ensure interpretation is consistent between
3752 // php 5 and php 7.
3753 $form->{$formvalue['name']} = $formvalue['value'];
3756 $processor->process_form($form, $preferences);
3758 if (!empty($preferences)) {
3759 set_user_preferences($preferences, $params['userid']);
3764 * Returns description of method result value
3766 * @return external_description
3767 * @since 3.2
3769 public static function message_processor_config_form_returns() {
3770 return null;
3774 * Returns description of method parameters
3776 * @return external_function_parameters
3777 * @since 3.2
3779 public static function get_message_processor_parameters() {
3780 return new external_function_parameters(
3781 array(
3782 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
3783 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
3789 * Get a message processor.
3791 * @param int $userid
3792 * @param string $name the name of the processor
3793 * @return external_description
3794 * @throws moodle_exception
3795 * @since 3.2
3797 public static function get_message_processor($userid = 0, $name) {
3798 global $USER, $PAGE, $CFG;
3800 // Check if messaging is enabled.
3801 if (empty($CFG->messaging)) {
3802 throw new moodle_exception('disabled', 'message');
3805 $params = self::validate_parameters(
3806 self::get_message_processor_parameters(),
3807 array(
3808 'userid' => $userid,
3809 'name' => $name,
3813 if (empty($params['userid'])) {
3814 $params['userid'] = $USER->id;
3817 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3818 core_user::require_active_user($user);
3819 self::validate_context(context_user::instance($params['userid']));
3821 $processor = get_message_processor($params['name']);
3823 $processoroutput = new \core_message\output\processor($processor, $user);
3824 $renderer = $PAGE->get_renderer('core_message');
3826 return $processoroutput->export_for_template($renderer);
3830 * Returns description of method result value
3832 * @return external_description
3833 * @since 3.2
3835 public static function get_message_processor_returns() {
3836 return new external_function_parameters(
3837 array(
3838 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
3839 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
3845 * Check that the user has enough permission to retrieve message or notifications preferences.
3847 * @param int $userid the user id requesting the preferences
3848 * @return stdClass full user object
3849 * @throws moodle_exception
3850 * @since Moodle 3.2
3852 protected static function validate_preferences_permissions($userid) {
3853 global $USER;
3855 if (empty($userid)) {
3856 $user = $USER;
3857 } else {
3858 $user = core_user::get_user($userid, '*', MUST_EXIST);
3859 core_user::require_active_user($user);
3862 $systemcontext = context_system::instance();
3863 self::validate_context($systemcontext);
3865 // Check access control.
3866 if ($user->id == $USER->id) {
3867 // Editing own message profile.
3868 require_capability('moodle/user:editownmessageprofile', $systemcontext);
3869 } else {
3870 // Teachers, parents, etc.
3871 $personalcontext = context_user::instance($user->id);
3872 require_capability('moodle/user:editmessageprofile', $personalcontext);
3874 return $user;
3878 * Returns a notification or message preference structure.
3880 * @return external_single_structure the structure
3881 * @since Moodle 3.2
3883 protected static function get_preferences_structure() {
3884 return new external_single_structure(
3885 array(
3886 'userid' => new external_value(PARAM_INT, 'User id'),
3887 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
3888 'processors' => new external_multiple_structure(
3889 new external_single_structure(
3890 array(
3891 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
3892 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
3893 'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
3894 'contextid' => new external_value(PARAM_INT, 'Context id'),
3895 'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
3898 'Config form values'
3900 'components' => new external_multiple_structure(
3901 new external_single_structure(
3902 array(
3903 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
3904 'notifications' => new external_multiple_structure(
3905 new external_single_structure(
3906 array(
3907 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
3908 'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
3909 'processors' => new external_multiple_structure(
3910 new external_single_structure(
3911 array(
3912 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
3913 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
3914 'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
3915 'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
3916 'loggedin' => new external_single_structure(
3917 array(
3918 'name' => new external_value(PARAM_NOTAGS, 'Name'),
3919 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
3920 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
3923 'loggedoff' => new external_single_structure(
3924 array(
3925 'name' => new external_value(PARAM_NOTAGS, 'Name'),
3926 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
3927 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
3932 'Processors values for this notification'
3936 'List of notificaitons for the component'
3940 'Available components'
3947 * Returns description of method parameters
3949 * @return external_function_parameters
3950 * @since 3.2
3952 public static function get_user_notification_preferences_parameters() {
3953 return new external_function_parameters(
3954 array(
3955 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
3961 * Get the notification preferences for a given user.
3963 * @param int $userid id of the user, 0 for current user
3964 * @return external_description
3965 * @throws moodle_exception
3966 * @since 3.2
3968 public static function get_user_notification_preferences($userid = 0) {
3969 global $PAGE;
3971 $params = self::validate_parameters(
3972 self::get_user_notification_preferences_parameters(),
3973 array(
3974 'userid' => $userid,
3977 $user = self::validate_preferences_permissions($params['userid']);
3979 $processors = get_message_processors();
3980 $providers = message_get_providers_for_user($user->id);
3981 $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
3982 $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
3984 $renderer = $PAGE->get_renderer('core_message');
3986 $result = array(
3987 'warnings' => array(),
3988 'preferences' => $notificationlist->export_for_template($renderer)
3990 return $result;
3994 * Returns description of method result value
3996 * @return external_description
3997 * @since 3.2
3999 public static function get_user_notification_preferences_returns() {
4000 return new external_function_parameters(
4001 array(
4002 'preferences' => self::get_preferences_structure(),
4003 'warnings' => new external_warnings(),
4009 * Returns description of method parameters
4011 * @return external_function_parameters
4012 * @since 3.2
4014 public static function get_user_message_preferences_parameters() {
4015 return new external_function_parameters(
4016 array(
4017 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
4023 * Get the notification preferences for a given user.
4025 * @param int $userid id of the user, 0 for current user
4026 * @return external_description
4027 * @throws moodle_exception
4028 * @since 3.2
4030 public static function get_user_message_preferences($userid = 0) {
4031 global $PAGE;
4033 $params = self::validate_parameters(
4034 self::get_user_message_preferences_parameters(),
4035 array(
4036 'userid' => $userid,
4040 $user = self::validate_preferences_permissions($params['userid']);
4042 // Filter out enabled, available system_configured and user_configured processors only.
4043 $readyprocessors = array_filter(get_message_processors(), function($processor) {
4044 return $processor->enabled &&
4045 $processor->configured &&
4046 $processor->object->is_user_configured() &&
4047 // Filter out processors that don't have and message preferences to configure.
4048 $processor->object->has_message_preferences();
4051 $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
4052 return $provider->component === 'moodle';
4054 $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
4055 $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
4056 $providers, $preferences, $user);
4058 $renderer = $PAGE->get_renderer('core_message');
4060 $result = array(
4061 'warnings' => array(),
4062 'preferences' => $notificationlistoutput->export_for_template($renderer),
4063 'blocknoncontacts' => \core_message\api::get_user_privacy_messaging_preference($user->id),
4065 return $result;
4069 * Returns description of method result value
4071 * @return external_description
4072 * @since 3.2
4074 public static function get_user_message_preferences_returns() {
4075 return new external_function_parameters(
4076 array(
4077 'preferences' => self::get_preferences_structure(),
4078 'blocknoncontacts' => new external_value(PARAM_INT, 'Privacy messaging setting to define who can message you'),
4079 'warnings' => new external_warnings(),
4085 * Returns description of method parameters for the favourite_conversations() method.
4087 * @return external_function_parameters
4089 public static function set_favourite_conversations_parameters() {
4090 return new external_function_parameters(
4091 array(
4092 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0),
4093 'conversations' => new external_multiple_structure(
4094 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0)
4101 * Favourite a conversation, or list of conversations for a user.
4103 * @param int $userid the id of the user, or 0 for the current user.
4104 * @param array $conversationids the list of conversations ids to favourite.
4105 * @return array
4106 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
4108 public static function set_favourite_conversations(int $userid, array $conversationids) {
4109 global $CFG, $USER;
4111 // All the business logic checks that really shouldn't be in here.
4112 if (empty($CFG->messaging)) {
4113 throw new moodle_exception('disabled', 'message');
4115 $params = [
4116 'userid' => $userid,
4117 'conversations' => $conversationids
4119 $params = self::validate_parameters(self::set_favourite_conversations_parameters(), $params);
4120 $systemcontext = context_system::instance();
4121 self::validate_context($systemcontext);
4123 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4124 throw new moodle_exception('You do not have permission to perform this action.');
4127 foreach ($params['conversations'] as $conversationid) {
4128 \core_message\api::set_favourite_conversation($conversationid, $params['userid']);
4131 return [];
4135 * Return a description of the returns for the create_user_favourite_conversations() method.
4137 * @return external_description
4139 public static function set_favourite_conversations_returns() {
4140 return new external_warnings();
4144 * Returns description of method parameters for unfavourite_conversations() method.
4146 * @return external_function_parameters
4148 public static function unset_favourite_conversations_parameters() {
4149 return new external_function_parameters(
4150 array(
4151 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0),
4152 'conversations' => new external_multiple_structure(
4153 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0)
4160 * Unfavourite a conversation, or list of conversations for a user.
4162 * @param int $userid the id of the user, or 0 for the current user.
4163 * @param array $conversationids the list of conversations ids unset as favourites.
4164 * @return array
4165 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
4167 public static function unset_favourite_conversations(int $userid, array $conversationids) {
4168 global $CFG, $USER;
4170 // All the business logic checks that really shouldn't be in here.
4171 if (empty($CFG->messaging)) {
4172 throw new moodle_exception('disabled', 'message');
4174 $params = [
4175 'userid' => $userid,
4176 'conversations' => $conversationids
4178 $params = self::validate_parameters(self::unset_favourite_conversations_parameters(), $params);
4179 $systemcontext = context_system::instance();
4180 self::validate_context($systemcontext);
4182 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4183 throw new moodle_exception('You do not have permission to perform this action.');
4186 foreach ($params['conversations'] as $conversationid) {
4187 \core_message\api::unset_favourite_conversation($conversationid, $params['userid']);
4190 return [];
4194 * Unset favourite conversations return description.
4196 * @return external_description
4198 public static function unset_favourite_conversations_returns() {
4199 return new external_warnings();
4203 * Returns description of method parameters for get_member_info() method.
4205 * @return external_function_parameters
4207 public static function get_member_info_parameters() {
4208 return new external_function_parameters(
4209 array(
4210 'referenceuserid' => new external_value(PARAM_INT, 'id of the user'),
4211 'userids' => new external_multiple_structure(
4212 new external_value(PARAM_INT, 'id of members to get')
4214 'includecontactrequests' => new external_value(PARAM_BOOL, 'include contact requests in response', VALUE_DEFAULT, false),
4215 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'include privacy info in response', VALUE_DEFAULT, false)
4221 * Returns conversation member info for the supplied users, relative to the supplied referenceuserid.
4223 * This is the basic structure used when returning members, and includes information about the relationship between each member
4224 * and the referenceuser, such as a whether the referenceuser has marked the member as a contact, or has blocked them.
4226 * @param int $referenceuserid the id of the user which check contact and blocked status.
4227 * @param array $userids
4228 * @return array the array of objects containing member info.
4229 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
4231 public static function get_member_info(
4232 int $referenceuserid,
4233 array $userids,
4234 bool $includecontactrequests = false,
4235 bool $includeprivacyinfo = false
4237 global $CFG, $USER;
4239 // All the business logic checks that really shouldn't be in here.
4240 if (empty($CFG->messaging)) {
4241 throw new moodle_exception('disabled', 'message');
4243 $params = [
4244 'referenceuserid' => $referenceuserid,
4245 'userids' => $userids,
4246 'includecontactrequests' => $includecontactrequests,
4247 'includeprivacyinfo' => $includeprivacyinfo
4249 $params = self::validate_parameters(self::get_member_info_parameters(), $params);
4250 $systemcontext = context_system::instance();
4251 self::validate_context($systemcontext);
4253 if (($USER->id != $referenceuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4254 throw new moodle_exception('You do not have permission to perform this action.');
4257 return \core_message\helper::get_member_info(
4258 $params['referenceuserid'],
4259 $params['userids'],
4260 $params['includecontactrequests'],
4261 $params['includeprivacyinfo']
4266 * Get member info return description.
4268 * @return external_description
4270 public static function get_member_info_returns() {
4271 return new external_multiple_structure(
4272 self::get_conversation_member_structure(true)