MDL-10965 course: search only courses with completion
[moodle.git] / message / externallib.php
blob9d1076017090166c9ea70a696ef7632427528375
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 $createdmessage = \core_message\api::send_message_to_conversation($USER->id, $params['conversationid'], $message['text'],
94 $message['textformat']);
95 $createdmessage->text = message_format_message_text((object) [
96 'smallmessage' => $createdmessage->text,
97 'fullmessageformat' => external_validate_format($message['textformat'])
98 ]);
99 $messages[] = $createdmessage;
102 return $messages;
106 * Returns description of method result value.
108 * @return external_description
109 * @since Moodle 3.6
111 public static function send_messages_to_conversation_returns() {
112 return new external_multiple_structure(
113 self::get_conversation_message_structure()
119 * Returns description of method parameters
121 * @return external_function_parameters
122 * @since Moodle 2.2
124 public static function send_instant_messages_parameters() {
125 return new external_function_parameters(
126 array(
127 'messages' => new external_multiple_structure(
128 new external_single_structure(
129 array(
130 'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
131 'text' => new external_value(PARAM_RAW, 'the text of the message'),
132 'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
133 '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),
142 * Send private messages from the current USER to other users
144 * @param array $messages An array of message to send.
145 * @return array
146 * @since Moodle 2.2
148 public static function send_instant_messages($messages = array()) {
149 global $CFG, $USER, $DB;
151 // Check if messaging is enabled.
152 if (empty($CFG->messaging)) {
153 throw new moodle_exception('disabled', 'message');
156 // Ensure the current user is allowed to run this function
157 $context = context_system::instance();
158 self::validate_context($context);
159 require_capability('moodle/site:sendmessage', $context);
161 $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
163 //retrieve all tousers of the messages
164 $receivers = array();
165 foreach($params['messages'] as $message) {
166 $receivers[] = $message['touserid'];
168 list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers);
169 $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
171 $resultmessages = array();
172 $messageids = array();
173 foreach ($params['messages'] as $message) {
174 $resultmsg = array(); //the infos about the success of the operation
176 // We are going to do some checking.
177 // Code should match /messages/index.php checks.
178 $success = true;
180 // Check the user exists.
181 if (empty($tousers[$message['touserid']])) {
182 $success = false;
183 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
186 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
187 // Check if the recipient can be messaged by the sender.
188 if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
189 $success = false;
190 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
193 // Now we can send the message (at least try).
194 if ($success) {
195 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
196 $success = message_post_message($USER, $tousers[$message['touserid']],
197 $message['text'], external_validate_format($message['textformat']));
200 // Build the resultmsg.
201 if (isset($message['clientmsgid'])) {
202 $resultmsg['clientmsgid'] = $message['clientmsgid'];
204 if ($success) {
205 $resultmsg['msgid'] = $success;
206 $resultmsg['text'] = message_format_message_text((object) [
207 'smallmessage' => $message['text'],
208 'fullmessageformat' => external_validate_format($message['textformat'])
210 $resultmsg['timecreated'] = time();
211 $messageids[] = $success;
212 } else {
213 // WARNINGS: for backward compatibility we return this errormessage.
214 // We should have thrown exceptions as these errors prevent results to be returned.
215 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
216 $resultmsg['msgid'] = -1;
217 $resultmsg['errormessage'] = $errormessage;
220 $resultmessages[] = $resultmsg;
223 if (!empty($messageids)) {
224 $messagerecords = $DB->get_records_list('messages', 'id', $messageids, '', 'id, conversationid');
225 $resultmessages = array_map(function($resultmessage) use ($messagerecords, $USER) {
226 $id = $resultmessage['msgid'];
227 $resultmessage['conversationid'] = isset($messagerecords[$id]) ? $messagerecords[$id]->conversationid : null;
228 $resultmessage['useridfrom'] = $USER->id;
229 return $resultmessage;
230 }, $resultmessages);
233 return $resultmessages;
237 * Returns description of method result value
239 * @return external_description
240 * @since Moodle 2.2
242 public static function send_instant_messages_returns() {
243 return new external_multiple_structure(
244 new external_single_structure(
245 array(
246 'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds: id of the created message if it succeeded, -1 when failed'),
247 'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
248 'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL),
249 'text' => new external_value(PARAM_RAW, 'The text of the message', VALUE_OPTIONAL),
250 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message', VALUE_OPTIONAL),
251 'conversationid' => new external_value(PARAM_INT, 'The conversation id for this message', VALUE_OPTIONAL),
252 'useridfrom' => new external_value(PARAM_INT, 'The user id who sent the message', VALUE_OPTIONAL),
259 * Create contacts parameters description.
261 * @deprecated since Moodle 3.6
262 * @return external_function_parameters
263 * @since Moodle 2.5
265 public static function create_contacts_parameters() {
266 return new external_function_parameters(
267 array(
268 'userids' => new external_multiple_structure(
269 new external_value(PARAM_INT, 'User ID'),
270 'List of user IDs'
272 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
273 current user', VALUE_DEFAULT, 0)
279 * Create contacts.
281 * @deprecated since Moodle 3.6
282 * @param array $userids array of user IDs.
283 * @param int $userid The id of the user we are creating the contacts for
284 * @return external_description
285 * @since Moodle 2.5
287 public static function create_contacts($userids, $userid = 0) {
288 global $CFG, $USER;
290 // Check if messaging is enabled.
291 if (empty($CFG->messaging)) {
292 throw new moodle_exception('disabled', 'message');
295 if (empty($userid)) {
296 $userid = $USER->id;
299 // Validate context.
300 $context = context_system::instance();
301 self::validate_context($context);
303 $params = array('userids' => $userids, 'userid' => $userid);
304 $params = self::validate_parameters(self::create_contacts_parameters(), $params);
306 $capability = 'moodle/site:manageallmessaging';
307 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
308 throw new required_capability_exception($context, $capability, 'nopermissions', '');
311 $warnings = array();
312 foreach ($params['userids'] as $id) {
313 if (!message_add_contact($id, 0, $params['userid'])) {
314 $warnings[] = array(
315 'item' => 'user',
316 'itemid' => $id,
317 'warningcode' => 'contactnotcreated',
318 'message' => 'The contact could not be created'
322 return $warnings;
326 * Create contacts return description.
328 * @deprecated since Moodle 3.6
329 * @return external_description
330 * @since Moodle 2.5
332 public static function create_contacts_returns() {
333 return new external_warnings();
337 * Marking the method as deprecated.
339 * @return bool
341 public static function create_contacts_is_deprecated() {
342 return true;
346 * Delete contacts parameters description.
348 * @return external_function_parameters
349 * @since Moodle 2.5
351 public static function delete_contacts_parameters() {
352 return new external_function_parameters(
353 array(
354 'userids' => new external_multiple_structure(
355 new external_value(PARAM_INT, 'User ID'),
356 'List of user IDs'
358 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
359 current user', VALUE_DEFAULT, 0)
365 * Delete contacts.
367 * @param array $userids array of user IDs.
368 * @param int $userid The id of the user we are deleting the contacts for
369 * @return null
370 * @since Moodle 2.5
372 public static function delete_contacts($userids, $userid = 0) {
373 global $CFG, $USER;
375 // Check if messaging is enabled.
376 if (empty($CFG->messaging)) {
377 throw new moodle_exception('disabled', 'message');
380 if (empty($userid)) {
381 $userid = $USER->id;
384 // Validate context.
385 $context = context_system::instance();
386 self::validate_context($context);
388 $params = array('userids' => $userids, 'userid' => $userid);
389 $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
391 $capability = 'moodle/site:manageallmessaging';
392 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
393 throw new required_capability_exception($context, $capability, 'nopermissions', '');
396 foreach ($params['userids'] as $id) {
397 \core_message\api::remove_contact($params['userid'], $id);
400 return null;
404 * Delete contacts return description.
406 * @return external_description
407 * @since Moodle 2.5
409 public static function delete_contacts_returns() {
410 return null;
414 * Mute conversations parameters description.
416 * @return external_function_parameters
418 public static function mute_conversations_parameters() {
419 return new external_function_parameters(
421 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
422 'conversationids' => new external_multiple_structure(
423 new external_value(PARAM_INT, 'id of the conversation', VALUE_REQUIRED)
430 * Mutes conversations.
432 * @param int $userid The id of the user who is blocking
433 * @param array $conversationids The list of conversations being muted
434 * @return external_description
436 public static function mute_conversations(int $userid, array $conversationids) {
437 global $CFG, $USER;
439 // Check if messaging is enabled.
440 if (empty($CFG->messaging)) {
441 throw new moodle_exception('disabled', 'message');
444 // Validate context.
445 $context = context_system::instance();
446 self::validate_context($context);
448 $params = ['userid' => $userid, 'conversationids' => $conversationids];
449 $params = self::validate_parameters(self::mute_conversations_parameters(), $params);
451 $capability = 'moodle/site:manageallmessaging';
452 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
453 throw new required_capability_exception($context, $capability, 'nopermissions', '');
456 foreach ($params['conversationids'] as $conversationid) {
457 if (!\core_message\api::is_conversation_muted($params['userid'], $conversationid)) {
458 \core_message\api::mute_conversation($params['userid'], $conversationid);
462 return [];
466 * Mute conversations return description.
468 * @return external_description
470 public static function mute_conversations_returns() {
471 return new external_warnings();
475 * Unmute conversations parameters description.
477 * @return external_function_parameters
479 public static function unmute_conversations_parameters() {
480 return new external_function_parameters(
482 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
483 'conversationids' => new external_multiple_structure(
484 new external_value(PARAM_INT, 'id of the conversation', VALUE_REQUIRED)
491 * Unmute conversations.
493 * @param int $userid The id of the user who is unblocking
494 * @param array $conversationids The list of conversations being muted
496 public static function unmute_conversations(int $userid, array $conversationids) {
497 global $CFG, $USER;
499 // Check if messaging is enabled.
500 if (empty($CFG->messaging)) {
501 throw new moodle_exception('disabled', 'message');
504 // Validate context.
505 $context = context_system::instance();
506 self::validate_context($context);
508 $params = ['userid' => $userid, 'conversationids' => $conversationids];
509 $params = self::validate_parameters(self::unmute_conversations_parameters(), $params);
511 $capability = 'moodle/site:manageallmessaging';
512 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
513 throw new required_capability_exception($context, $capability, 'nopermissions', '');
516 foreach ($params['conversationids'] as $conversationid) {
517 \core_message\api::unmute_conversation($params['userid'], $conversationid);
520 return [];
524 * Unmute conversations return description.
526 * @return external_description
528 public static function unmute_conversations_returns() {
529 return new external_warnings();
533 * Block user parameters description.
535 * @return external_function_parameters
537 public static function block_user_parameters() {
538 return new external_function_parameters(
540 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
541 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
547 * Blocks a user.
549 * @param int $userid The id of the user who is blocking
550 * @param int $blockeduserid The id of the user being blocked
551 * @return external_description
553 public static function block_user(int $userid, int $blockeduserid) {
554 global $CFG, $USER;
556 // Check if messaging is enabled.
557 if (empty($CFG->messaging)) {
558 throw new moodle_exception('disabled', 'message');
561 // Validate context.
562 $context = context_system::instance();
563 self::validate_context($context);
565 $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
566 $params = self::validate_parameters(self::block_user_parameters(), $params);
568 $capability = 'moodle/site:manageallmessaging';
569 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
570 throw new required_capability_exception($context, $capability, 'nopermissions', '');
573 if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
574 \core_message\api::block_user($params['userid'], $params['blockeduserid']);
577 return [];
581 * Block user return description.
583 * @return external_description
585 public static function block_user_returns() {
586 return new external_warnings();
590 * Unblock user parameters description.
592 * @return external_function_parameters
594 public static function unblock_user_parameters() {
595 return new external_function_parameters(
597 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
598 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
604 * Unblock user.
606 * @param int $userid The id of the user who is unblocking
607 * @param int $unblockeduserid The id of the user being unblocked
609 public static function unblock_user(int $userid, int $unblockeduserid) {
610 global $CFG, $USER;
612 // Check if messaging is enabled.
613 if (empty($CFG->messaging)) {
614 throw new moodle_exception('disabled', 'message');
617 // Validate context.
618 $context = context_system::instance();
619 self::validate_context($context);
621 $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
622 $params = self::validate_parameters(self::unblock_user_parameters(), $params);
624 $capability = 'moodle/site:manageallmessaging';
625 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
626 throw new required_capability_exception($context, $capability, 'nopermissions', '');
629 \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
631 return [];
635 * Unblock user return description.
637 * @return external_description
639 public static function unblock_user_returns() {
640 return new external_warnings();
644 * Block contacts parameters description.
646 * @deprecated since Moodle 3.6
647 * @return external_function_parameters
648 * @since Moodle 2.5
650 public static function block_contacts_parameters() {
651 return new external_function_parameters(
652 array(
653 'userids' => new external_multiple_structure(
654 new external_value(PARAM_INT, 'User ID'),
655 'List of user IDs'
657 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
658 current user', VALUE_DEFAULT, 0)
664 * Block contacts.
666 * @deprecated since Moodle 3.6
667 * @param array $userids array of user IDs.
668 * @param int $userid The id of the user we are blocking the contacts for
669 * @return external_description
670 * @since Moodle 2.5
672 public static function block_contacts($userids, $userid = 0) {
673 global $CFG, $USER;
675 // Check if messaging is enabled.
676 if (empty($CFG->messaging)) {
677 throw new moodle_exception('disabled', 'message');
680 if (empty($userid)) {
681 $userid = $USER->id;
684 // Validate context.
685 $context = context_system::instance();
686 self::validate_context($context);
688 $params = array('userids' => $userids, 'userid' => $userid);
689 $params = self::validate_parameters(self::block_contacts_parameters(), $params);
691 $capability = 'moodle/site:manageallmessaging';
692 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
693 throw new required_capability_exception($context, $capability, 'nopermissions', '');
696 $warnings = array();
697 foreach ($params['userids'] as $id) {
698 if (!message_block_contact($id, $params['userid'])) {
699 $warnings[] = array(
700 'item' => 'user',
701 'itemid' => $id,
702 'warningcode' => 'contactnotblocked',
703 'message' => 'The contact could not be blocked'
707 return $warnings;
711 * Block contacts return description.
713 * @deprecated since Moodle 3.6
714 * @return external_description
715 * @since Moodle 2.5
717 public static function block_contacts_returns() {
718 return new external_warnings();
722 * Marking the method as deprecated.
724 * @return bool
726 public static function block_contacts_is_deprecated() {
727 return true;
731 * Unblock contacts parameters description.
733 * @deprecated since Moodle 3.6
734 * @return external_function_parameters
735 * @since Moodle 2.5
737 public static function unblock_contacts_parameters() {
738 return new external_function_parameters(
739 array(
740 'userids' => new external_multiple_structure(
741 new external_value(PARAM_INT, 'User ID'),
742 'List of user IDs'
744 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
745 current user', VALUE_DEFAULT, 0)
751 * Unblock contacts.
753 * @param array $userids array of user IDs.
754 * @param int $userid The id of the user we are unblocking the contacts for
755 * @return null
756 * @since Moodle 2.5
758 public static function unblock_contacts($userids, $userid = 0) {
759 global $CFG, $USER;
761 // Check if messaging is enabled.
762 if (empty($CFG->messaging)) {
763 throw new moodle_exception('disabled', 'message');
766 if (empty($userid)) {
767 $userid = $USER->id;
770 // Validate context.
771 $context = context_system::instance();
772 self::validate_context($context);
774 $params = array('userids' => $userids, 'userid' => $userid);
775 $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
777 $capability = 'moodle/site:manageallmessaging';
778 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
779 throw new required_capability_exception($context, $capability, 'nopermissions', '');
782 foreach ($params['userids'] as $id) {
783 message_unblock_contact($id, $params['userid']);
786 return null;
790 * Unblock contacts return description.
792 * @deprecated since Moodle 3.6
793 * @return external_description
794 * @since Moodle 2.5
796 public static function unblock_contacts_returns() {
797 return null;
801 * Marking the method as deprecated.
803 * @return bool
805 public static function unblock_contacts_is_deprecated() {
806 return true;
810 * Returns contact requests parameters description.
812 * @return external_function_parameters
814 public static function get_contact_requests_parameters() {
815 return new external_function_parameters(
817 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for'),
818 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
819 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
825 * Handles returning the contact requests for a user.
827 * This also includes the user data necessary to display information
828 * about the user.
830 * It will not include blocked users.
832 * @param int $userid The id of the user we want to get the contact requests for
833 * @param int $limitfrom
834 * @param int $limitnum
836 public static function get_contact_requests(int $userid, int $limitfrom = 0, int $limitnum = 0) {
837 global $CFG, $USER;
839 // Check if messaging is enabled.
840 if (empty($CFG->messaging)) {
841 throw new moodle_exception('disabled', 'message');
844 // Validate context.
845 $context = context_system::instance();
846 self::validate_context($context);
848 $params = [
849 'userid' => $userid,
850 'limitfrom' => $limitfrom,
851 'limitnum' => $limitnum
853 $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
855 $capability = 'moodle/site:manageallmessaging';
856 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
857 throw new required_capability_exception($context, $capability, 'nopermissions', '');
860 return \core_message\api::get_contact_requests($params['userid'], $params['limitfrom'], $params['limitnum']);
864 * Returns the contact requests return description.
866 * @return external_description
868 public static function get_contact_requests_returns() {
869 return new external_multiple_structure(
870 self::get_conversation_member_structure()
875 * Returns the number of contact requests the user has received parameters description.
877 * @return external_function_parameters
879 public static function get_received_contact_requests_count_parameters() {
880 return new external_function_parameters(
881 array(
882 'userid' => new external_value(PARAM_INT, 'The id of the user we want to return the number of ' .
883 'received contact requests for', VALUE_REQUIRED),
889 * Returns the number of contact requests the user has received.
891 * @param int $userid The ID of the user we want to return the number of received contact requests for
892 * @return external_value
894 public static function get_received_contact_requests_count(int $userid) {
895 global $CFG, $USER;
897 // Check if messaging is enabled.
898 if (empty($CFG->messaging)) {
899 throw new moodle_exception('disabled', 'message');
902 // Validate context.
903 $context = context_system::instance();
904 self::validate_context($context);
906 $params = [
907 'userid' => $userid,
909 $params = self::validate_parameters(self::get_received_contact_requests_count_parameters(), $params);
911 $capability = 'moodle/site:manageallmessaging';
912 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
913 throw new required_capability_exception($context, $capability, 'nopermissions', '');
916 return \core_message\api::get_received_contact_requests_count($params['userid']);
920 * Returns the number of contact requests the user has received return description.
922 * @return external_value
924 public static function get_received_contact_requests_count_returns() {
925 return new external_value(PARAM_INT, 'The number of received contact requests');
929 * Returns get conversation members parameters description.
931 * @return external_function_parameters
933 public static function get_conversation_members_parameters() {
934 return new external_function_parameters(
936 'userid' => new external_value(PARAM_INT, 'The id of the user we are performing this action on behalf of'),
937 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation'),
938 'includecontactrequests' => new external_value(PARAM_BOOL, 'Do we want to include contact requests?',
939 VALUE_DEFAULT, false),
940 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Do we want to include privacy info?',
941 VALUE_DEFAULT, false),
942 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
943 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
949 * Returns a list of conversation members.
951 * @param int $userid The user we are returning the conversation members for, used by helper::get_member_info.
952 * @param int $conversationid The id of the conversation
953 * @param bool $includecontactrequests Do we want to include contact requests with this data?
954 * @param bool $includeprivacyinfo Do we want to include privacy info?
955 * @param int $limitfrom
956 * @param int $limitnum
957 * @return array
959 public static function get_conversation_members(int $userid, int $conversationid, bool $includecontactrequests = false,
960 bool $includeprivacyinfo = false, int $limitfrom = 0, int $limitnum = 0) {
961 global $CFG, $USER;
963 // Check if messaging is enabled.
964 if (empty($CFG->messaging)) {
965 throw new moodle_exception('disabled', 'message');
968 // Validate context.
969 $context = context_system::instance();
970 self::validate_context($context);
972 $params = [
973 'userid' => $userid,
974 'conversationid' => $conversationid,
975 'includecontactrequests' => $includecontactrequests,
976 'includeprivacyinfo' => $includeprivacyinfo,
977 'limitfrom' => $limitfrom,
978 'limitnum' => $limitnum
980 $params = self::validate_parameters(self::get_conversation_members_parameters(), $params);
982 $capability = 'moodle/site:manageallmessaging';
983 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
984 throw new required_capability_exception($context, $capability, 'nopermissions', '');
987 // The user needs to be a part of the conversation before querying who the members are.
988 if (!\core_message\api::is_user_in_conversation($params['userid'], $params['conversationid'])) {
989 throw new moodle_exception('You are not a member of this conversation.');
992 return \core_message\api::get_conversation_members($params['userid'], $params['conversationid'], $params['includecontactrequests'],
993 $params['includeprivacyinfo'], $params['limitfrom'], $params['limitnum']);
997 * Returns the get conversation members return description.
999 * @return external_description
1001 public static function get_conversation_members_returns() {
1002 return new external_multiple_structure(
1003 self::get_conversation_member_structure()
1008 * Creates a contact request parameters description.
1010 * @return external_function_parameters
1012 public static function create_contact_request_parameters() {
1013 return new external_function_parameters(
1015 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
1016 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
1022 * Creates a contact request.
1024 * @param int $userid The id of the user who is creating the contact request
1025 * @param int $requesteduserid The id of the user being requested
1027 public static function create_contact_request(int $userid, int $requesteduserid) {
1028 global $CFG, $USER;
1030 // Check if messaging is enabled.
1031 if (empty($CFG->messaging)) {
1032 throw new moodle_exception('disabled', 'message');
1035 // Validate context.
1036 $context = context_system::instance();
1037 self::validate_context($context);
1039 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
1040 $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
1042 $capability = 'moodle/site:manageallmessaging';
1043 if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
1044 throw new required_capability_exception($context, $capability, 'nopermissions', '');
1047 $result = [
1048 'warnings' => []
1051 if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
1052 $result['warnings'][] = [
1053 'item' => 'user',
1054 'itemid' => $params['requesteduserid'],
1055 'warningcode' => 'cannotcreatecontactrequest',
1056 'message' => 'You are unable to create a contact request for this user'
1058 } else {
1059 if ($requests = \core_message\api::get_contact_requests_between_users($params['userid'], $params['requesteduserid'])) {
1060 // There should only ever be one but just in case there are multiple then we can return the first.
1061 $result['request'] = array_shift($requests);
1062 } else {
1063 $result['request'] = \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
1067 return $result;
1071 * Creates a contact request return description.
1073 * @return external_description
1075 public static function create_contact_request_returns() {
1076 return new external_single_structure(
1077 array(
1078 'request' => new external_single_structure(
1079 array(
1080 'id' => new external_value(PARAM_INT, 'Message id'),
1081 'userid' => new external_value(PARAM_INT, 'User from id'),
1082 'requesteduserid' => new external_value(PARAM_INT, 'User to id'),
1083 'timecreated' => new external_value(PARAM_INT, 'Time created'),
1085 'request record',
1086 VALUE_OPTIONAL
1088 'warnings' => new external_warnings()
1094 * Confirm a contact request parameters description.
1096 * @return external_function_parameters
1098 public static function confirm_contact_request_parameters() {
1099 return new external_function_parameters(
1101 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
1102 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
1108 * Confirm a contact request.
1110 * @param int $userid The id of the user who is creating the contact request
1111 * @param int $requesteduserid The id of the user being requested
1113 public static function confirm_contact_request(int $userid, int $requesteduserid) {
1114 global $CFG, $USER;
1116 // Check if messaging is enabled.
1117 if (empty($CFG->messaging)) {
1118 throw new moodle_exception('disabled', 'message');
1121 // Validate context.
1122 $context = context_system::instance();
1123 self::validate_context($context);
1125 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
1126 $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
1128 $capability = 'moodle/site:manageallmessaging';
1129 if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
1130 throw new required_capability_exception($context, $capability, 'nopermissions', '');
1133 \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
1135 return [];
1139 * Confirm a contact request return description.
1141 * @return external_description
1143 public static function confirm_contact_request_returns() {
1144 return new external_warnings();
1148 * Declines a contact request parameters description.
1150 * @return external_function_parameters
1152 public static function decline_contact_request_parameters() {
1153 return new external_function_parameters(
1155 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
1156 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
1162 * Declines a contact request.
1164 * @param int $userid The id of the user who is creating the contact request
1165 * @param int $requesteduserid The id of the user being requested
1167 public static function decline_contact_request(int $userid, int $requesteduserid) {
1168 global $CFG, $USER;
1170 // Check if messaging is enabled.
1171 if (empty($CFG->messaging)) {
1172 throw new moodle_exception('disabled', 'message');
1175 // Validate context.
1176 $context = context_system::instance();
1177 self::validate_context($context);
1179 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
1180 $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
1182 $capability = 'moodle/site:manageallmessaging';
1183 if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
1184 throw new required_capability_exception($context, $capability, 'nopermissions', '');
1187 \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
1189 return [];
1193 * Declines a contact request return description.
1195 * @return external_description
1197 public static function decline_contact_request_returns() {
1198 return new external_warnings();
1202 * Return the structure of a message area contact.
1204 * @return external_single_structure
1205 * @since Moodle 3.2
1207 private static function get_messagearea_contact_structure() {
1208 return new external_single_structure(
1209 array(
1210 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
1211 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1212 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1213 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1214 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
1215 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
1216 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
1217 'lastmessagedate' => new external_value(PARAM_INT, 'Timestamp for last message', VALUE_DEFAULT, null),
1218 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
1219 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1220 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1221 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
1222 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1223 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1224 VALUE_DEFAULT, null),
1225 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation', VALUE_DEFAULT, null),
1231 * Return the structure of a conversation.
1233 * @return external_single_structure
1234 * @since Moodle 3.6
1236 private static function get_conversation_structure() {
1237 return new external_single_structure(
1238 array(
1239 'id' => new external_value(PARAM_INT, 'The conversation id'),
1240 'name' => new external_value(PARAM_TEXT, 'The conversation name, if set', VALUE_DEFAULT, null),
1241 'subname' => new external_value(PARAM_TEXT, 'A subtitle for the conversation name, if set', VALUE_DEFAULT, null),
1242 'imageurl' => new external_value(PARAM_URL, 'A link to the conversation picture, if set', VALUE_DEFAULT, null),
1243 'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group)'),
1244 'membercount' => new external_value(PARAM_INT, 'Total number of conversation members'),
1245 'ismuted' => new external_value(PARAM_BOOL, 'If the user muted this conversation'),
1246 'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked this conversation as a favourite'),
1247 'isread' => new external_value(PARAM_BOOL, 'If the user has read all messages in the conversation'),
1248 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1249 VALUE_DEFAULT, null),
1250 'members' => new external_multiple_structure(
1251 self::get_conversation_member_structure()
1253 'messages' => new external_multiple_structure(
1254 self::get_conversation_message_structure()
1261 * Return the structure of a conversation member.
1263 * @return external_single_structure
1264 * @since Moodle 3.6
1266 private static function get_conversation_member_structure() {
1267 $result = [
1268 'id' => new external_value(PARAM_INT, 'The user id'),
1269 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1270 'profileurl' => new external_value(PARAM_URL, 'The link to the user\'s profile page'),
1271 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1272 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1273 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1274 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1275 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1276 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
1277 'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
1278 'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
1279 'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
1282 $result['contactrequests'] = new external_multiple_structure(
1283 new external_single_structure(
1285 'id' => new external_value(PARAM_INT, 'The id of the contact request'),
1286 'userid' => new external_value(PARAM_INT, 'The id of the user who created the contact request'),
1287 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user confirming the request'),
1288 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the contact request'),
1290 ), 'The contact requests', VALUE_OPTIONAL
1293 $result['conversations'] = new external_multiple_structure(new external_single_structure(
1294 array(
1295 'id' => new external_value(PARAM_INT, 'Conversations id'),
1296 'type' => new external_value(PARAM_INT, 'Conversation type: private or public'),
1297 'name' => new external_value(PARAM_TEXT, 'Multilang compatible conversation name'. VALUE_OPTIONAL),
1298 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the conversation'),
1299 ), 'information about conversation', VALUE_OPTIONAL),
1300 'Conversations between users', VALUE_OPTIONAL
1303 return new external_single_structure(
1304 $result
1309 * Return the structure of a message area message.
1311 * @return external_single_structure
1312 * @since Moodle 3.6
1314 private static function get_conversation_message_structure() {
1315 return new external_single_structure(
1316 array(
1317 'id' => new external_value(PARAM_INT, 'The id of the message'),
1318 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1319 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1320 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1326 * Return the structure of a message area message.
1328 * @return external_single_structure
1329 * @since Moodle 3.2
1331 private static function get_messagearea_message_structure() {
1332 return new external_single_structure(
1333 array(
1334 'id' => new external_value(PARAM_INT, 'The id of the message'),
1335 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1336 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
1337 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1338 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
1339 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
1340 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
1341 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
1342 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1343 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
1349 * Get messagearea search users in course parameters.
1351 * @deprecated since 3.6
1353 * @return external_function_parameters
1354 * @since 3.2
1356 public static function data_for_messagearea_search_users_in_course_parameters() {
1357 return new external_function_parameters(
1358 array(
1359 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1360 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
1361 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1362 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1363 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1369 * Get messagearea search users in course results.
1371 * @deprecated since 3.6
1373 * @param int $userid The id of the user who is performing the search
1374 * @param int $courseid The id of the course
1375 * @param string $search The string being searched
1376 * @param int $limitfrom
1377 * @param int $limitnum
1378 * @return stdClass
1379 * @throws moodle_exception
1380 * @since 3.2
1382 public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
1383 $limitnum = 0) {
1384 global $CFG, $PAGE, $USER;
1386 // Check if messaging is enabled.
1387 if (empty($CFG->messaging)) {
1388 throw new moodle_exception('disabled', 'message');
1391 $systemcontext = context_system::instance();
1393 $params = array(
1394 'userid' => $userid,
1395 'courseid' => $courseid,
1396 'search' => $search,
1397 'limitfrom' => $limitfrom,
1398 'limitnum' => $limitnum
1400 $params = self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
1401 self::validate_context($systemcontext);
1403 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1404 throw new moodle_exception('You do not have permission to perform this action.');
1407 $users = \core_message\api::search_users_in_course(
1408 $params['userid'],
1409 $params['courseid'],
1410 $params['search'],
1411 $params['limitfrom'],
1412 $params['limitnum']
1414 $results = new \core_message\output\messagearea\user_search_results($users);
1416 $renderer = $PAGE->get_renderer('core_message');
1417 return $results->export_for_template($renderer);
1421 * Get messagearea search users in course returns.
1423 * @deprecated since 3.6
1425 * @return external_single_structure
1426 * @since 3.2
1428 public static function data_for_messagearea_search_users_in_course_returns() {
1429 return new external_single_structure(
1430 array(
1431 'contacts' => new external_multiple_structure(
1432 self::get_messagearea_contact_structure()
1439 * Marking the method as deprecated.
1441 * @return bool
1443 public static function data_for_messagearea_search_users_in_course_is_deprecated() {
1444 return true;
1448 * Get messagearea search users parameters.
1450 * @deprecated since 3.6
1452 * @return external_function_parameters
1453 * @since 3.2
1455 public static function data_for_messagearea_search_users_parameters() {
1456 return new external_function_parameters(
1457 array(
1458 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1459 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1460 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1466 * Get messagearea search users results.
1468 * @deprecated since 3.6
1470 * @param int $userid The id of the user who is performing the search
1471 * @param string $search The string being searched
1472 * @param int $limitnum
1473 * @return stdClass
1474 * @throws moodle_exception
1475 * @since 3.2
1477 public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1478 global $CFG, $PAGE, $USER;
1480 // Check if messaging is enabled.
1481 if (empty($CFG->messaging)) {
1482 throw new moodle_exception('disabled', 'message');
1485 $systemcontext = context_system::instance();
1487 $params = array(
1488 'userid' => $userid,
1489 'search' => $search,
1490 'limitnum' => $limitnum
1492 $params = self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1493 self::validate_context($systemcontext);
1495 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1496 throw new moodle_exception('You do not have permission to perform this action.');
1499 list($contacts, $courses, $noncontacts) = \core_message\api::search_users(
1500 $params['userid'],
1501 $params['search'],
1502 $params['limitnum']
1505 $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1507 $renderer = $PAGE->get_renderer('core_message');
1508 return $search->export_for_template($renderer);
1512 * Get messagearea search users returns.
1514 * @deprecated since 3.6
1516 * @return external_single_structure
1517 * @since 3.2
1519 public static function data_for_messagearea_search_users_returns() {
1520 return new external_single_structure(
1521 array(
1522 'contacts' => new external_multiple_structure(
1523 self::get_messagearea_contact_structure()
1525 'courses' => new external_multiple_structure(
1526 new external_single_structure(
1527 array(
1528 'id' => new external_value(PARAM_INT, 'The course id'),
1529 'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1530 'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1534 'noncontacts' => new external_multiple_structure(
1535 self::get_messagearea_contact_structure()
1542 * Marking the method as deprecated.
1544 * @return bool
1546 public static function data_for_messagearea_search_users_is_deprecated() {
1547 return true;
1551 * Get messagearea message search users parameters.
1553 * @return external_function_parameters
1554 * @since 3.6
1556 public static function message_search_users_parameters() {
1557 return new external_function_parameters(
1558 array(
1559 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1560 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1561 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1562 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1568 * Get search users results.
1570 * @param int $userid The id of the user who is performing the search
1571 * @param string $search The string being searched
1572 * @param int $limitfrom
1573 * @param int $limitnum
1574 * @return array
1575 * @throws moodle_exception
1576 * @since 3.6
1578 public static function message_search_users($userid, $search, $limitfrom = 0, $limitnum = 0) {
1579 global $USER;
1581 $systemcontext = context_system::instance();
1583 $params = array(
1584 'userid' => $userid,
1585 'search' => $search,
1586 'limitfrom' => $limitfrom,
1587 'limitnum' => $limitnum
1589 $params = self::validate_parameters(self::message_search_users_parameters(), $params);
1590 self::validate_context($systemcontext);
1592 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1593 throw new moodle_exception('You do not have permission to perform this action.');
1596 list($contacts, $noncontacts) = \core_message\api::message_search_users(
1597 $params['userid'],
1598 $params['search'],
1599 $params['limitfrom'],
1600 $params['limitnum']);
1602 return array('contacts' => $contacts, 'noncontacts' => $noncontacts);
1606 * Get messagearea message search users returns.
1608 * @return external_single_structure
1609 * @since 3.2
1611 public static function message_search_users_returns() {
1612 return new external_single_structure(
1613 array(
1614 'contacts' => new external_multiple_structure(
1615 self::get_conversation_member_structure()
1617 'noncontacts' => new external_multiple_structure(
1618 self::get_conversation_member_structure()
1625 * Get messagearea search messages parameters.
1627 * @return external_function_parameters
1628 * @since 3.2
1630 public static function data_for_messagearea_search_messages_parameters() {
1631 return new external_function_parameters(
1632 array(
1633 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1634 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1635 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1636 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1642 * Get messagearea search messages results.
1644 * @param int $userid The id of the user who is performing the search
1645 * @param string $search The string being searched
1646 * @param int $limitfrom
1647 * @param int $limitnum
1648 * @return stdClass
1649 * @throws moodle_exception
1650 * @since 3.2
1652 public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1653 global $CFG, $USER;
1655 // Check if messaging is enabled.
1656 if (empty($CFG->messaging)) {
1657 throw new moodle_exception('disabled', 'message');
1660 $systemcontext = context_system::instance();
1662 $params = array(
1663 'userid' => $userid,
1664 'search' => $search,
1665 'limitfrom' => $limitfrom,
1666 'limitnum' => $limitnum
1669 $params = self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1670 self::validate_context($systemcontext);
1672 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1673 throw new moodle_exception('You do not have permission to perform this action.');
1676 $messages = \core_message\api::search_messages(
1677 $params['userid'],
1678 $params['search'],
1679 $params['limitfrom'],
1680 $params['limitnum']
1683 $data = new \stdClass();
1684 $data->contacts = [];
1685 foreach ($messages as $message) {
1686 $contact = new \stdClass();
1687 $contact->userid = $message->userid;
1688 $contact->fullname = $message->fullname;
1689 $contact->profileimageurl = $message->profileimageurl;
1690 $contact->profileimageurlsmall = $message->profileimageurlsmall;
1691 $contact->messageid = $message->messageid;
1692 $contact->ismessaging = $message->ismessaging;
1693 $contact->sentfromcurrentuser = false;
1694 if ($message->lastmessage) {
1695 if ($message->userid !== $message->useridfrom) {
1696 $contact->sentfromcurrentuser = true;
1698 $contact->lastmessage = shorten_text($message->lastmessage, 60);
1699 } else {
1700 $contact->lastmessage = null;
1702 $contact->lastmessagedate = $message->lastmessagedate;
1703 $contact->showonlinestatus = is_null($message->isonline) ? false : true;
1704 $contact->isonline = $message->isonline;
1705 $contact->isblocked = $message->isblocked;
1706 $contact->isread = $message->isread;
1707 $contact->unreadcount = $message->unreadcount;
1708 $contact->conversationid = $message->conversationid;
1710 $data->contacts[] = $contact;
1713 return $data;
1717 * Get messagearea search messages returns.
1719 * @return external_single_structure
1720 * @since 3.2
1722 public static function data_for_messagearea_search_messages_returns() {
1723 return new external_single_structure(
1724 array(
1725 'contacts' => new external_multiple_structure(
1726 self::get_messagearea_contact_structure()
1733 * Get conversations parameters.
1735 * @return external_function_parameters
1736 * @since 3.6
1738 public static function get_conversations_parameters() {
1739 return new external_function_parameters(
1740 array(
1741 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1742 'limitfrom' => new external_value(PARAM_INT, 'The offset to start at', VALUE_DEFAULT, 0),
1743 'limitnum' => new external_value(PARAM_INT, 'Limit number of conversations to this', VALUE_DEFAULT, 0),
1744 'type' => new external_value(PARAM_INT, 'Filter by type', VALUE_DEFAULT, null),
1745 'favourites' => new external_value(PARAM_BOOL, 'Whether to restrict the results to contain NO favourite
1746 conversations (false), ONLY favourite conversation (true), or ignore any restriction altogether (null)',
1747 VALUE_DEFAULT, null),
1754 * Get the list of conversations for the user.
1756 * @param int $userid The id of the user who is performing the search
1757 * @param int $limitfrom
1758 * @param int $limitnum
1759 * @param int|null $type
1760 * @param bool|null $favourites
1761 * @return stdClass
1762 * @throws \moodle_exception if the messaging feature is disabled on the site.
1763 * @since 3.2
1765 public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null) {
1766 global $CFG, $USER;
1768 // All the standard BL checks.
1769 if (empty($CFG->messaging)) {
1770 throw new moodle_exception('disabled', 'message');
1773 $params = array(
1774 'userid' => $userid,
1775 'limitfrom' => $limitfrom,
1776 'limitnum' => $limitnum,
1777 'type' => $type,
1778 'favourites' => $favourites
1780 $params = self::validate_parameters(self::get_conversations_parameters(), $params);
1782 $systemcontext = context_system::instance();
1783 self::validate_context($systemcontext);
1785 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1786 throw new moodle_exception('You do not have permission to perform this action.');
1789 $conversations = \core_message\api::get_conversations(
1790 $params['userid'],
1791 $params['limitfrom'],
1792 $params['limitnum'],
1793 $params['type'],
1794 $params['favourites']
1797 return (object) ['conversations' => $conversations];
1801 * Get conversations returns.
1803 * @return external_single_structure
1804 * @since 3.6
1806 public static function get_conversations_returns() {
1807 return new external_single_structure(
1809 'conversations' => new external_multiple_structure(
1810 self::get_conversation_structure(true)
1817 * Get conversation parameters.
1819 * @return external_function_parameters
1821 public static function get_conversation_parameters() {
1822 return new external_function_parameters(
1823 array(
1824 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1825 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation to fetch'),
1826 'includecontactrequests' => new external_value(PARAM_BOOL, 'Include contact requests in the members'),
1827 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Include privacy info in the members'),
1828 'memberlimit' => new external_value(PARAM_INT, 'Limit for number of members', VALUE_DEFAULT, 0),
1829 'memberoffset' => new external_value(PARAM_INT, 'Offset for member list', VALUE_DEFAULT, 0),
1830 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
1831 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
1832 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
1838 * Get a single conversation.
1840 * @param int $userid The user id to get the conversation for
1841 * @param int $conversationid The id of the conversation to fetch
1842 * @param bool $includecontactrequests Should contact requests be included between members
1843 * @param bool $includeprivacyinfo Should privacy info be included between members
1844 * @param int $memberlimit Limit number of members to load
1845 * @param int $memberoffset Offset members by this amount
1846 * @param int $messagelimit Limit number of messages to load
1847 * @param int $messageoffset Offset the messages
1848 * @param bool $newestmessagesfirst Order messages by newest first
1849 * @return stdClass
1850 * @throws \moodle_exception if the messaging feature is disabled on the site.
1852 public static function get_conversation(
1853 int $userid,
1854 int $conversationid,
1855 bool $includecontactrequests = false,
1856 bool $includeprivacyinfo = false,
1857 int $memberlimit = 0,
1858 int $memberoffset = 0,
1859 int $messagelimit = 0,
1860 int $messageoffset = 0,
1861 bool $newestmessagesfirst = true
1863 global $CFG, $DB, $USER;
1865 // All the standard BL checks.
1866 if (empty($CFG->messaging)) {
1867 throw new moodle_exception('disabled', 'message');
1870 $params = [
1871 'userid' => $userid,
1872 'conversationid' => $conversationid,
1873 'includecontactrequests' => $includecontactrequests,
1874 'includeprivacyinfo' => $includeprivacyinfo,
1875 'memberlimit' => $memberlimit,
1876 'memberoffset' => $memberoffset,
1877 'messagelimit' => $messagelimit,
1878 'messageoffset' => $messageoffset,
1879 'newestmessagesfirst' => $newestmessagesfirst
1881 self::validate_parameters(self::get_conversation_parameters(), $params);
1883 $systemcontext = context_system::instance();
1884 self::validate_context($systemcontext);
1886 $conversation = \core_message\api::get_conversation(
1887 $params['userid'],
1888 $params['conversationid'],
1889 $params['includecontactrequests'],
1890 $params['includeprivacyinfo'],
1891 $params['memberlimit'],
1892 $params['memberoffset'],
1893 $params['messagelimit'],
1894 $params['messageoffset'],
1895 $params['newestmessagesfirst']
1898 if ($conversation) {
1899 return $conversation;
1900 } else {
1901 // We have to throw an exception here because the external functions annoyingly
1902 // don't accept null to be returned for a single structure.
1903 throw new \moodle_exception('errorconversationdoesnotexist', 'message');
1908 * Get conversation returns.
1910 * @return external_single_structure
1912 public static function get_conversation_returns() {
1913 return self::get_conversation_structure();
1917 * Get conversation parameters.
1919 * @return external_function_parameters
1921 public static function get_conversation_between_users_parameters() {
1922 return new external_function_parameters(
1923 array(
1924 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1925 'otheruserid' => new external_value(PARAM_INT, 'The other user id'),
1926 'includecontactrequests' => new external_value(PARAM_BOOL, 'Include contact requests in the members'),
1927 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Include privacy info in the members'),
1928 'memberlimit' => new external_value(PARAM_INT, 'Limit for number of members', VALUE_DEFAULT, 0),
1929 'memberoffset' => new external_value(PARAM_INT, 'Offset for member list', VALUE_DEFAULT, 0),
1930 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
1931 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
1932 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
1938 * Get a single conversation between users.
1940 * @param int $userid The user id to get the conversation for
1941 * @param int $otheruserid The other user id
1942 * @param bool $includecontactrequests Should contact requests be included between members
1943 * @param bool $includeprivacyinfo Should privacy info be included between members
1944 * @param int $memberlimit Limit number of members to load
1945 * @param int $memberoffset Offset members by this amount
1946 * @param int $messagelimit Limit number of messages to load
1947 * @param int $messageoffset Offset the messages
1948 * @param bool $newestmessagesfirst Order messages by newest first
1949 * @return stdClass
1950 * @throws \moodle_exception if the messaging feature is disabled on the site.
1952 public static function get_conversation_between_users(
1953 int $userid,
1954 int $otheruserid,
1955 bool $includecontactrequests = false,
1956 bool $includeprivacyinfo = false,
1957 int $memberlimit = 0,
1958 int $memberoffset = 0,
1959 int $messagelimit = 0,
1960 int $messageoffset = 0,
1961 bool $newestmessagesfirst = true
1963 global $CFG, $DB, $USER;
1965 // All the standard BL checks.
1966 if (empty($CFG->messaging)) {
1967 throw new moodle_exception('disabled', 'message');
1970 $params = [
1971 'userid' => $userid,
1972 'otheruserid' => $otheruserid,
1973 'includecontactrequests' => $includecontactrequests,
1974 'includeprivacyinfo' => $includeprivacyinfo,
1975 'memberlimit' => $memberlimit,
1976 'memberoffset' => $memberoffset,
1977 'messagelimit' => $messagelimit,
1978 'messageoffset' => $messageoffset,
1979 'newestmessagesfirst' => $newestmessagesfirst
1981 self::validate_parameters(self::get_conversation_between_users_parameters(), $params);
1983 $systemcontext = context_system::instance();
1984 self::validate_context($systemcontext);
1986 $conversationid = \core_message\api::get_conversation_between_users([$params['userid'], $params['otheruserid']]);
1987 $conversation = null;
1989 if ($conversationid) {
1990 $conversation = \core_message\api::get_conversation(
1991 $params['userid'],
1992 $conversationid,
1993 $params['includecontactrequests'],
1994 $params['includeprivacyinfo'],
1995 $params['memberlimit'],
1996 $params['memberoffset'],
1997 $params['messagelimit'],
1998 $params['messageoffset'],
1999 $params['newestmessagesfirst']
2003 if ($conversation) {
2004 return $conversation;
2005 } else {
2006 // We have to throw an exception here because the external functions annoyingly
2007 // don't accept null to be returned for a single structure.
2008 throw new \moodle_exception('errorconversationdoesnotexist', 'message');
2013 * Get conversation returns.
2015 * @return external_single_structure
2017 public static function get_conversation_between_users_returns() {
2018 return self::get_conversation_structure(true);
2022 * The messagearea conversations parameters.
2024 * @deprecated since 3.6
2025 * @return external_function_parameters
2026 * @since 3.2
2028 public static function data_for_messagearea_conversations_parameters() {
2029 return new external_function_parameters(
2030 array(
2031 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
2032 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2033 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
2039 * Get messagearea conversations.
2041 * NOTE FOR FINAL DEPRECATION:
2042 * When removing this method, please also consider removal of get_conversations_legacy_formatter()
2043 * from the \core_message\helper class. This helper method was used solely to format the new get_conversations() return data
2044 * into the old format used here, and in message/index.php. If we no longer need either of these, then that method can be
2045 * removed.
2047 * @deprecated since 3.6
2048 * @param int $userid The id of the user who we are viewing conversations for
2049 * @param int $limitfrom
2050 * @param int $limitnum
2051 * @return stdClass
2052 * @throws moodle_exception
2053 * @since 3.2
2055 public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
2056 global $CFG, $PAGE, $USER;
2058 // Check if messaging is enabled.
2059 if (empty($CFG->messaging)) {
2060 throw new moodle_exception('disabled', 'message');
2063 $systemcontext = context_system::instance();
2065 $params = array(
2066 'userid' => $userid,
2067 'limitfrom' => $limitfrom,
2068 'limitnum' => $limitnum
2070 $params = self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
2071 self::validate_context($systemcontext);
2073 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2074 throw new moodle_exception('You do not have permission to perform this action.');
2077 $conversations = \core_message\api::get_conversations($params['userid'], $params['limitfrom'], $params['limitnum']);
2079 // Format the conversations in the legacy style, as the get_conversations method has since been changed.
2080 $conversations = \core_message\helper::get_conversations_legacy_formatter($conversations);
2082 $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
2084 $renderer = $PAGE->get_renderer('core_message');
2085 return $conversations->export_for_template($renderer);
2089 * The messagearea conversations return structure.
2091 * @deprecated since 3.6
2092 * @return external_single_structure
2093 * @since 3.2
2095 public static function data_for_messagearea_conversations_returns() {
2096 return new external_single_structure(
2097 array(
2098 'contacts' => new external_multiple_structure(
2099 self::get_messagearea_contact_structure()
2106 * Marking the method as deprecated.
2108 * @return bool
2110 public static function data_for_messagearea_conversations_is_deprecated() {
2111 return true;
2115 * The messagearea contacts return parameters.
2117 * @deprecated since 3.6
2118 * @return external_function_parameters
2119 * @since 3.2
2121 public static function data_for_messagearea_contacts_parameters() {
2122 return self::data_for_messagearea_conversations_parameters();
2126 * Get messagearea contacts parameters.
2128 * @deprecated since 3.6
2129 * @param int $userid The id of the user who we are viewing conversations for
2130 * @param int $limitfrom
2131 * @param int $limitnum
2132 * @return stdClass
2133 * @throws moodle_exception
2134 * @since 3.2
2136 public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
2137 global $CFG, $PAGE, $USER;
2139 // Check if messaging is enabled.
2140 if (empty($CFG->messaging)) {
2141 throw new moodle_exception('disabled', 'message');
2144 $systemcontext = context_system::instance();
2146 $params = array(
2147 'userid' => $userid,
2148 'limitfrom' => $limitfrom,
2149 'limitnum' => $limitnum
2151 $params = self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
2152 self::validate_context($systemcontext);
2154 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2155 throw new moodle_exception('You do not have permission to perform this action.');
2158 $contacts = \core_message\api::get_contacts($params['userid'], $params['limitfrom'], $params['limitnum']);
2159 $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
2161 $renderer = $PAGE->get_renderer('core_message');
2162 return $contacts->export_for_template($renderer);
2166 * The messagearea contacts return structure.
2168 * @deprecated since 3.6
2169 * @return external_single_structure
2170 * @since 3.2
2172 public static function data_for_messagearea_contacts_returns() {
2173 return self::data_for_messagearea_conversations_returns();
2177 * Marking the method as deprecated.
2179 * @return bool
2181 public static function data_for_messagearea_contacts_is_deprecated() {
2182 return true;
2186 * The messagearea messages parameters.
2188 * @deprecated since 3.6
2189 * @return external_function_parameters
2190 * @since 3.2
2192 public static function data_for_messagearea_messages_parameters() {
2193 return new external_function_parameters(
2194 array(
2195 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2196 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2197 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2198 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
2199 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
2200 'timefrom' => new external_value(PARAM_INT,
2201 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
2207 * Get messagearea messages.
2209 * @deprecated since 3.6
2210 * @param int $currentuserid The current user's id
2211 * @param int $otheruserid The other user's id
2212 * @param int $limitfrom
2213 * @param int $limitnum
2214 * @param boolean $newest
2215 * @return stdClass
2216 * @throws moodle_exception
2217 * @since 3.2
2219 public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
2220 $newest = false, $timefrom = 0) {
2221 global $CFG, $PAGE, $USER;
2223 // Check if messaging is enabled.
2224 if (empty($CFG->messaging)) {
2225 throw new moodle_exception('disabled', 'message');
2228 $systemcontext = context_system::instance();
2230 $params = array(
2231 'currentuserid' => $currentuserid,
2232 'otheruserid' => $otheruserid,
2233 'limitfrom' => $limitfrom,
2234 'limitnum' => $limitnum,
2235 'newest' => $newest,
2236 'timefrom' => $timefrom,
2238 $params = self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
2239 self::validate_context($systemcontext);
2241 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2242 throw new moodle_exception('You do not have permission to perform this action.');
2245 if ($params['newest']) {
2246 $sort = 'timecreated DESC';
2247 } else {
2248 $sort = 'timecreated ASC';
2251 // We need to enforce a one second delay on messages to avoid race conditions of current
2252 // messages still being sent.
2254 // There is a chance that we could request messages before the current time's
2255 // second has elapsed and while other messages are being sent in that same second. In which
2256 // case those messages will be lost.
2258 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
2259 if (!empty($params['timefrom'])) {
2260 $timeto = time() - 1;
2261 } else {
2262 $timeto = 0;
2265 // No requesting messages from the current time, as stated above.
2266 if ($params['timefrom'] == time()) {
2267 $messages = [];
2268 } else {
2269 $messages = \core_message\api::get_messages($params['currentuserid'], $params['otheruserid'], $params['limitfrom'],
2270 $params['limitnum'], $sort, $params['timefrom'], $timeto);
2273 $messages = new \core_message\output\messagearea\messages($params['currentuserid'], $params['otheruserid'], $messages);
2275 $renderer = $PAGE->get_renderer('core_message');
2276 return $messages->export_for_template($renderer);
2280 * The messagearea messages return structure.
2282 * @deprecated since 3.6
2283 * @return external_single_structure
2284 * @since 3.2
2286 public static function data_for_messagearea_messages_returns() {
2287 return new external_single_structure(
2288 array(
2289 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
2290 the messages on behalf of?'),
2291 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2292 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2293 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
2294 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2295 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2296 'messages' => new external_multiple_structure(
2297 self::get_messagearea_message_structure()
2299 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
2305 * Marking the method as deprecated.
2307 * @return bool
2309 public static function data_for_messagearea_messages_is_deprecated() {
2310 return true;
2314 * The conversation messages parameters.
2316 * @return external_function_parameters
2317 * @since 3.6
2319 public static function get_conversation_messages_parameters() {
2320 return new external_function_parameters(
2321 array(
2322 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2323 'convid' => new external_value(PARAM_INT, 'The conversation id'),
2324 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2325 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
2326 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
2327 'timefrom' => new external_value(PARAM_INT,
2328 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
2334 * Get conversation messages.
2336 * @param int $currentuserid The current user's id.
2337 * @param int $convid The conversation id.
2338 * @param int $limitfrom Return a subset of records, starting at this point (optional).
2339 * @param int $limitnum Return a subset comprising this many records in total (optional, required if $limitfrom is set).
2340 * @param bool $newest True for getting first newest messages, false otherwise.
2341 * @param int $timefrom The time from the conversation messages to get.
2342 * @return stdClass The messages and members who have sent some of these messages.
2343 * @throws moodle_exception
2344 * @since 3.6
2346 public static function get_conversation_messages(int $currentuserid, int $convid, int $limitfrom = 0, int $limitnum = 0,
2347 bool $newest = false, int $timefrom = 0) {
2348 global $CFG, $PAGE, $USER;
2350 // Check if messaging is enabled.
2351 if (empty($CFG->messaging)) {
2352 throw new moodle_exception('disabled', 'message');
2355 $systemcontext = context_system::instance();
2357 $params = array(
2358 'currentuserid' => $currentuserid,
2359 'convid' => $convid,
2360 'limitfrom' => $limitfrom,
2361 'limitnum' => $limitnum,
2362 'newest' => $newest,
2363 'timefrom' => $timefrom,
2365 $params = self::validate_parameters(self::get_conversation_messages_parameters(), $params);
2366 self::validate_context($systemcontext);
2368 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2369 throw new moodle_exception('You do not have permission to perform this action.');
2372 $sort = $newest ? 'timecreated DESC' : 'timecreated ASC';
2374 // We need to enforce a one second delay on messages to avoid race conditions of current
2375 // messages still being sent.
2377 // There is a chance that we could request messages before the current time's
2378 // second has elapsed and while other messages are being sent in that same second. In which
2379 // case those messages will be lost.
2381 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
2382 $timeto = empty($params['timefrom']) ? 0 : time() - 1;
2384 // No requesting messages from the current time, as stated above.
2385 if ($params['timefrom'] == time()) {
2386 $messages = [];
2387 } else {
2388 $messages = \core_message\api::get_conversation_messages(
2389 $params['currentuserid'],
2390 $params['convid'],
2391 $params['limitfrom'],
2392 $params['limitnum'],
2393 $sort,
2394 $params['timefrom'],
2395 $timeto);
2398 return $messages;
2402 * The messagearea messages return structure.
2404 * @return external_single_structure
2405 * @since 3.6
2407 public static function get_conversation_messages_returns() {
2408 return new external_single_structure(
2409 array(
2410 'id' => new external_value(PARAM_INT, 'The conversation id'),
2411 'members' => new external_multiple_structure(
2412 self::get_conversation_member_structure()
2414 'messages' => new external_multiple_structure(
2415 self::get_conversation_message_structure()
2422 * The user contacts return parameters.
2424 * @return external_function_parameters
2426 public static function get_user_contacts_parameters() {
2427 return new external_function_parameters(
2428 array(
2429 'userid' => new external_value(PARAM_INT, 'The id of the user who we retrieving the contacts for'),
2430 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2431 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
2437 * Get user contacts.
2439 * @param int $userid The id of the user who we are viewing conversations for
2440 * @param int $limitfrom
2441 * @param int $limitnum
2442 * @return array
2443 * @throws moodle_exception
2445 public static function get_user_contacts(int $userid, int $limitfrom = 0, int $limitnum = 0) {
2446 global $CFG, $USER;
2448 // Check if messaging is enabled.
2449 if (empty($CFG->messaging)) {
2450 throw new moodle_exception('disabled', 'message');
2453 $systemcontext = context_system::instance();
2455 $params = array(
2456 'userid' => $userid,
2457 'limitfrom' => $limitfrom,
2458 'limitnum' => $limitnum
2460 $params = self::validate_parameters(self::get_user_contacts_parameters(), $params);
2461 self::validate_context($systemcontext);
2463 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2464 throw new moodle_exception('You do not have permission to perform this action.');
2467 return \core_message\api::get_user_contacts($params['userid'], $params['limitfrom'], $params['limitnum']);
2471 * The user contacts return structure.
2473 * @return external_multiple_structure
2475 public static function get_user_contacts_returns() {
2476 return new external_multiple_structure(
2477 self::get_conversation_member_structure()
2482 * The get most recent message return parameters.
2484 * @deprecated since 3.6
2485 * @return external_function_parameters
2486 * @since 3.2
2488 public static function data_for_messagearea_get_most_recent_message_parameters() {
2489 return new external_function_parameters(
2490 array(
2491 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2492 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2498 * Get the most recent message in a conversation.
2500 * @deprecated since 3.6
2501 * @param int $currentuserid The current user's id
2502 * @param int $otheruserid The other user's id
2503 * @return stdClass
2504 * @throws moodle_exception
2505 * @since 3.2
2507 public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
2508 global $CFG, $PAGE, $USER;
2510 // Check if messaging is enabled.
2511 if (empty($CFG->messaging)) {
2512 throw new moodle_exception('disabled', 'message');
2515 $systemcontext = context_system::instance();
2517 $params = array(
2518 'currentuserid' => $currentuserid,
2519 'otheruserid' => $otheruserid
2521 $params = self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
2522 self::validate_context($systemcontext);
2524 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2525 throw new moodle_exception('You do not have permission to perform this action.');
2528 $message = \core_message\api::get_most_recent_message($params['currentuserid'], $params['otheruserid']);
2529 $message = new \core_message\output\messagearea\message($message);
2531 $renderer = $PAGE->get_renderer('core_message');
2532 return $message->export_for_template($renderer);
2536 * The get most recent message return structure.
2538 * @deprecated since 3.6
2539 * @return external_single_structure
2540 * @since 3.2
2542 public static function data_for_messagearea_get_most_recent_message_returns() {
2543 return self::get_messagearea_message_structure();
2547 * Marking the method as deprecated.
2549 * @return bool
2551 public static function data_for_messagearea_get_most_recent_message_is_deprecated() {
2552 return true;
2556 * The get profile parameters.
2558 * @deprecated since 3.6
2559 * @return external_function_parameters
2560 * @since 3.2
2562 public static function data_for_messagearea_get_profile_parameters() {
2563 return new external_function_parameters(
2564 array(
2565 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2566 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
2572 * Get the profile information for a contact.
2574 * @deprecated since 3.6
2575 * @param int $currentuserid The current user's id
2576 * @param int $otheruserid The id of the user whose profile we are viewing
2577 * @return stdClass
2578 * @throws moodle_exception
2579 * @since 3.2
2581 public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
2582 global $CFG, $PAGE, $USER;
2584 // Check if messaging is enabled.
2585 if (empty($CFG->messaging)) {
2586 throw new moodle_exception('disabled', 'message');
2589 $systemcontext = context_system::instance();
2591 $params = array(
2592 'currentuserid' => $currentuserid,
2593 'otheruserid' => $otheruserid
2595 $params = self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
2596 self::validate_context($systemcontext);
2598 if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2599 throw new moodle_exception('You do not have permission to perform this action.');
2602 $profile = \core_message\api::get_profile($params['currentuserid'], $params['otheruserid']);
2603 $profile = new \core_message\output\messagearea\profile($profile);
2605 $renderer = $PAGE->get_renderer('core_message');
2606 return $profile->export_for_template($renderer);
2610 * The get profile return structure.
2612 * @deprecated since 3.6
2613 * @return external_single_structure
2614 * @since 3.2
2616 public static function data_for_messagearea_get_profile_returns() {
2617 return new external_single_structure(
2618 array(
2619 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
2620 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
2621 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
2622 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
2623 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
2624 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
2625 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
2626 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2627 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2628 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
2629 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
2635 * Marking the method as deprecated.
2637 * @return bool
2639 public static function data_for_messagearea_get_profile_is_deprecated() {
2640 return true;
2644 * Get contacts parameters description.
2646 * @deprecated since 3.6
2647 * @return external_function_parameters
2648 * @since Moodle 2.5
2650 public static function get_contacts_parameters() {
2651 return new external_function_parameters(array());
2655 * Get contacts.
2657 * @deprecated since 3.6
2658 * @return external_description
2659 * @since Moodle 2.5
2661 public static function get_contacts() {
2662 global $CFG, $PAGE, $USER;
2664 // Check if messaging is enabled.
2665 if (empty($CFG->messaging)) {
2666 throw new moodle_exception('disabled', 'message');
2669 require_once($CFG->dirroot . '/user/lib.php');
2671 $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
2672 $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
2673 foreach ($contacts as $contact) {
2674 // Set the mode.
2675 $mode = 'offline';
2676 if (\core_message\helper::is_online($contact->lastaccess)) {
2677 $mode = 'online';
2680 $newcontact = array(
2681 'id' => $contact->id,
2682 'fullname' => fullname($contact),
2683 'unread' => $contact->messagecount
2686 $userpicture = new user_picture($contact);
2687 $userpicture->size = 1; // Size f1.
2688 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2689 $userpicture->size = 0; // Size f2.
2690 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2692 $allcontacts[$mode][$contact->id] = $newcontact;
2695 $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
2696 foreach ($strangers as $contact) {
2697 $newcontact = array(
2698 'id' => $contact->id,
2699 'fullname' => fullname($contact),
2700 'unread' => $contact->messagecount
2703 $userpicture = new user_picture($contact);
2704 $userpicture->size = 1; // Size f1.
2705 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2706 $userpicture->size = 0; // Size f2.
2707 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2709 $allcontacts['strangers'][$contact->id] = $newcontact;
2712 // Add noreply user and support user to the list, if they don't exist.
2713 $supportuser = core_user::get_support_user();
2714 if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
2715 $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
2716 if ($supportuser->messagecount > 0) {
2717 $supportuser->fullname = fullname($supportuser);
2718 $supportuser->unread = $supportuser->messagecount;
2719 $allcontacts['strangers'][$supportuser->id] = $supportuser;
2723 $noreplyuser = core_user::get_noreply_user();
2724 if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
2725 $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
2726 if ($noreplyuser->messagecount > 0) {
2727 $noreplyuser->fullname = fullname($noreplyuser);
2728 $noreplyuser->unread = $noreplyuser->messagecount;
2729 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
2733 return $allcontacts;
2737 * Get contacts return description.
2739 * @deprecated since 3.6
2740 * @return external_description
2741 * @since Moodle 2.5
2743 public static function get_contacts_returns() {
2744 return new external_single_structure(
2745 array(
2746 'online' => new external_multiple_structure(
2747 new external_single_structure(
2748 array(
2749 'id' => new external_value(PARAM_INT, 'User ID'),
2750 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2751 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2752 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2753 'unread' => new external_value(PARAM_INT, 'Unread message count')
2756 'List of online contacts'
2758 'offline' => new external_multiple_structure(
2759 new external_single_structure(
2760 array(
2761 'id' => new external_value(PARAM_INT, 'User ID'),
2762 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2763 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2764 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2765 'unread' => new external_value(PARAM_INT, 'Unread message count')
2768 'List of offline contacts'
2770 'strangers' => new external_multiple_structure(
2771 new external_single_structure(
2772 array(
2773 'id' => new external_value(PARAM_INT, 'User ID'),
2774 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2775 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2776 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2777 'unread' => new external_value(PARAM_INT, 'Unread message count')
2780 'List of users that are not in the user\'s contact list but have sent a message'
2787 * Marking the method as deprecated.
2789 * @return bool
2791 public static function get_contacts_is_deprecated() {
2792 return true;
2796 * Search contacts parameters description.
2798 * @return external_function_parameters
2799 * @since Moodle 2.5
2801 public static function search_contacts_parameters() {
2802 return new external_function_parameters(
2803 array(
2804 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
2805 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
2806 VALUE_DEFAULT, false)
2812 * Search contacts.
2814 * @param string $searchtext query string.
2815 * @param bool $onlymycourses limit the search to the user's courses only.
2816 * @return external_description
2817 * @since Moodle 2.5
2819 public static function search_contacts($searchtext, $onlymycourses = false) {
2820 global $CFG, $USER, $PAGE;
2821 require_once($CFG->dirroot . '/user/lib.php');
2823 // Check if messaging is enabled.
2824 if (empty($CFG->messaging)) {
2825 throw new moodle_exception('disabled', 'message');
2828 require_once($CFG->libdir . '/enrollib.php');
2830 $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
2831 $params = self::validate_parameters(self::search_contacts_parameters(), $params);
2833 // Extra validation, we do not allow empty queries.
2834 if ($params['searchtext'] === '') {
2835 throw new moodle_exception('querystringcannotbeempty');
2838 $courseids = array();
2839 if ($params['onlymycourses']) {
2840 $mycourses = enrol_get_my_courses(array('id'));
2841 foreach ($mycourses as $mycourse) {
2842 $courseids[] = $mycourse->id;
2844 } else {
2845 $courseids[] = SITEID;
2848 // Retrieving the users matching the query.
2849 $users = message_search_users($courseids, $params['searchtext']);
2850 $results = array();
2851 foreach ($users as $user) {
2852 $results[$user->id] = $user;
2855 // Reorganising information.
2856 foreach ($results as &$user) {
2857 $newuser = array(
2858 'id' => $user->id,
2859 'fullname' => fullname($user)
2862 // Avoid undefined property notice as phone not specified.
2863 $user->phone1 = null;
2864 $user->phone2 = null;
2866 $userpicture = new user_picture($user);
2867 $userpicture->size = 1; // Size f1.
2868 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2869 $userpicture->size = 0; // Size f2.
2870 $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2872 $user = $newuser;
2875 return $results;
2879 * Search contacts return description.
2881 * @return external_description
2882 * @since Moodle 2.5
2884 public static function search_contacts_returns() {
2885 return new external_multiple_structure(
2886 new external_single_structure(
2887 array(
2888 'id' => new external_value(PARAM_INT, 'User ID'),
2889 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2890 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2891 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
2894 'List of contacts'
2899 * Get messages parameters description.
2901 * @return external_function_parameters
2902 * @since 2.8
2904 public static function get_messages_parameters() {
2905 return new external_function_parameters(
2906 array(
2907 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2908 'useridfrom' => new external_value(
2909 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2910 VALUE_DEFAULT, 0),
2911 'type' => new external_value(
2912 PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
2913 VALUE_DEFAULT, 'both'),
2914 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
2915 'newestfirst' => new external_value(
2916 PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
2917 VALUE_DEFAULT, true),
2918 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
2919 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
2925 * Get messages function implementation.
2927 * @since 2.8
2928 * @throws invalid_parameter_exception
2929 * @throws moodle_exception
2930 * @param int $useridto the user id who received the message
2931 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2932 * @param string $type type of message to return, expected values: notifications, conversations and both
2933 * @param bool $read true for retreiving read messages, false for unread
2934 * @param bool $newestfirst true for ordering by newest first, false for oldest first
2935 * @param int $limitfrom limit from
2936 * @param int $limitnum limit num
2937 * @return external_description
2939 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
2940 $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
2941 global $CFG, $USER;
2943 $warnings = array();
2945 $params = array(
2946 'useridto' => $useridto,
2947 'useridfrom' => $useridfrom,
2948 'type' => $type,
2949 'read' => $read,
2950 'newestfirst' => $newestfirst,
2951 'limitfrom' => $limitfrom,
2952 'limitnum' => $limitnum
2955 $params = self::validate_parameters(self::get_messages_parameters(), $params);
2957 $context = context_system::instance();
2958 self::validate_context($context);
2960 $useridto = $params['useridto'];
2961 $useridfrom = $params['useridfrom'];
2962 $type = $params['type'];
2963 $read = $params['read'];
2964 $newestfirst = $params['newestfirst'];
2965 $limitfrom = $params['limitfrom'];
2966 $limitnum = $params['limitnum'];
2968 $allowedvalues = array('notifications', 'conversations', 'both');
2969 if (!in_array($type, $allowedvalues)) {
2970 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
2971 'allowed values are: ' . implode(',', $allowedvalues));
2974 // Check if private messaging between users is allowed.
2975 if (empty($CFG->messaging)) {
2976 // If we are retreiving only conversations, and messaging is disabled, throw an exception.
2977 if ($type == "conversations") {
2978 throw new moodle_exception('disabled', 'message');
2980 if ($type == "both") {
2981 $warning = array();
2982 $warning['item'] = 'message';
2983 $warning['itemid'] = $USER->id;
2984 $warning['warningcode'] = '1';
2985 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
2986 Only notifications will be returned';
2987 $warnings[] = $warning;
2991 if (!empty($useridto)) {
2992 if (core_user::is_real_user($useridto)) {
2993 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2994 } else {
2995 throw new moodle_exception('invaliduser');
2999 if (!empty($useridfrom)) {
3000 // We use get_user here because the from user can be the noreply or support user.
3001 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3004 // Check if the current user is the sender/receiver or just a privileged user.
3005 if ($useridto != $USER->id and $useridfrom != $USER->id and
3006 !has_capability('moodle/site:readallmessages', $context)) {
3007 throw new moodle_exception('accessdenied', 'admin');
3010 // Which type of messages to retrieve.
3011 $notifications = -1;
3012 if ($type != 'both') {
3013 $notifications = ($type == 'notifications') ? 1 : 0;
3016 $orderdirection = $newestfirst ? 'DESC' : 'ASC';
3017 $sort = "mr.timecreated $orderdirection";
3019 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
3020 $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
3022 // In some cases, we don't need to get the to/from user objects from the sql query.
3023 $userfromfullname = '';
3024 $usertofullname = '';
3026 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
3027 if (!empty($useridto)) {
3028 $usertofullname = fullname($userto, $canviewfullname);
3029 // The user from may or may not be filled.
3030 if (!empty($useridfrom)) {
3031 $userfromfullname = fullname($userfrom, $canviewfullname);
3033 } else {
3034 // If the useridto field is empty, the useridfrom must be filled.
3035 $userfromfullname = fullname($userfrom, $canviewfullname);
3037 foreach ($messages as $mid => $message) {
3039 // Do not return deleted messages.
3040 if (!$message->notification) {
3041 if (($useridto == $USER->id and $message->timeusertodeleted) or
3042 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
3043 unset($messages[$mid]);
3044 continue;
3048 // We need to get the user from the query.
3049 if (empty($userfromfullname)) {
3050 // Check for non-reply and support users.
3051 if (core_user::is_real_user($message->useridfrom)) {
3052 $user = new stdClass();
3053 $user = username_load_fields_from_object($user, $message, 'userfrom');
3054 $message->userfromfullname = fullname($user, $canviewfullname);
3055 } else {
3056 $user = core_user::get_user($message->useridfrom);
3057 $message->userfromfullname = fullname($user, $canviewfullname);
3059 } else {
3060 $message->userfromfullname = $userfromfullname;
3063 // We need to get the user from the query.
3064 if (empty($usertofullname)) {
3065 $user = new stdClass();
3066 $user = username_load_fields_from_object($user, $message, 'userto');
3067 $message->usertofullname = fullname($user, $canviewfullname);
3068 } else {
3069 $message->usertofullname = $usertofullname;
3072 $message->text = message_format_message_text($message);
3073 $messages[$mid] = (array) $message;
3077 $results = array(
3078 'messages' => $messages,
3079 'warnings' => $warnings
3082 return $results;
3086 * Get messages return description.
3088 * @return external_single_structure
3089 * @since 2.8
3091 public static function get_messages_returns() {
3092 return new external_single_structure(
3093 array(
3094 'messages' => new external_multiple_structure(
3095 new external_single_structure(
3096 array(
3097 'id' => new external_value(PARAM_INT, 'Message id'),
3098 'useridfrom' => new external_value(PARAM_INT, 'User from id'),
3099 'useridto' => new external_value(PARAM_INT, 'User to id'),
3100 'subject' => new external_value(PARAM_TEXT, 'The message subject'),
3101 'text' => new external_value(PARAM_RAW, 'The message text formated'),
3102 'fullmessage' => new external_value(PARAM_RAW, 'The message'),
3103 'fullmessageformat' => new external_format_value('fullmessage'),
3104 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
3105 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
3106 'notification' => new external_value(PARAM_INT, 'Is a notification?'),
3107 'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
3108 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
3109 'timecreated' => new external_value(PARAM_INT, 'Time created'),
3110 'timeread' => new external_value(PARAM_INT, 'Time read'),
3111 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
3112 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
3113 ), 'message'
3116 'warnings' => new external_warnings()
3122 * Mark all notifications as read parameters description.
3124 * @return external_function_parameters
3125 * @since 3.2
3127 public static function mark_all_notifications_as_read_parameters() {
3128 return new external_function_parameters(
3129 array(
3130 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3131 'useridfrom' => new external_value(
3132 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3133 VALUE_DEFAULT, 0),
3139 * Mark all notifications as read function.
3141 * @since 3.2
3142 * @throws invalid_parameter_exception
3143 * @throws moodle_exception
3144 * @param int $useridto the user id who received the message
3145 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
3146 * @return external_description
3148 public static function mark_all_notifications_as_read($useridto, $useridfrom) {
3149 global $USER;
3151 $params = self::validate_parameters(
3152 self::mark_all_notifications_as_read_parameters(),
3153 array(
3154 'useridto' => $useridto,
3155 'useridfrom' => $useridfrom,
3159 $context = context_system::instance();
3160 self::validate_context($context);
3162 $useridto = $params['useridto'];
3163 $useridfrom = $params['useridfrom'];
3165 if (!empty($useridto)) {
3166 if (core_user::is_real_user($useridto)) {
3167 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3168 } else {
3169 throw new moodle_exception('invaliduser');
3173 if (!empty($useridfrom)) {
3174 // We use get_user here because the from user can be the noreply or support user.
3175 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3178 // Check if the current user is the sender/receiver or just a privileged user.
3179 if ($useridto != $USER->id and $useridfrom != $USER->id and
3180 // The deleteanymessage cap seems more reasonable here than readallmessages.
3181 !has_capability('moodle/site:deleteanymessage', $context)) {
3182 throw new moodle_exception('accessdenied', 'admin');
3185 \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
3187 return true;
3191 * Mark all notifications as read return description.
3193 * @return external_single_structure
3194 * @since 3.2
3196 public static function mark_all_notifications_as_read_returns() {
3197 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
3201 * Get unread conversations count parameters description.
3203 * @return external_function_parameters
3204 * @since 3.2
3206 public static function get_unread_conversations_count_parameters() {
3207 return new external_function_parameters(
3208 array(
3209 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3215 * Get unread messages count function.
3217 * @since 3.2
3218 * @throws invalid_parameter_exception
3219 * @throws moodle_exception
3220 * @param int $useridto the user id who received the message
3221 * @return external_description
3223 public static function get_unread_conversations_count($useridto) {
3224 global $USER, $CFG;
3226 // Check if messaging is enabled.
3227 if (empty($CFG->messaging)) {
3228 throw new moodle_exception('disabled', 'message');
3231 $params = self::validate_parameters(
3232 self::get_unread_conversations_count_parameters(),
3233 array('useridto' => $useridto)
3236 $context = context_system::instance();
3237 self::validate_context($context);
3239 $useridto = $params['useridto'];
3241 if (!empty($useridto)) {
3242 if (core_user::is_real_user($useridto)) {
3243 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3244 } else {
3245 throw new moodle_exception('invaliduser');
3247 } else {
3248 $useridto = $USER->id;
3251 // Check if the current user is the receiver or just a privileged user.
3252 if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
3253 throw new moodle_exception('accessdenied', 'admin');
3256 return \core_message\api::count_unread_conversations($userto);
3260 * Get unread conversations count return description.
3262 * @return external_single_structure
3263 * @since 3.2
3265 public static function get_unread_conversations_count_returns() {
3266 return new external_value(PARAM_INT, 'The count of unread messages for the user');
3270 * Get blocked users parameters description.
3272 * @return external_function_parameters
3273 * @since 2.9
3275 public static function get_blocked_users_parameters() {
3276 return new external_function_parameters(
3277 array(
3278 'userid' => new external_value(PARAM_INT,
3279 'the user whose blocked users we want to retrieve',
3280 VALUE_REQUIRED),
3286 * Retrieve a list of users blocked
3288 * @param int $userid the user whose blocked users we want to retrieve
3289 * @return external_description
3290 * @since 2.9
3292 public static function get_blocked_users($userid) {
3293 global $CFG, $USER, $PAGE;
3295 // Warnings array, it can be empty at the end but is mandatory.
3296 $warnings = array();
3298 // Validate params.
3299 $params = array(
3300 'userid' => $userid
3302 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
3303 $userid = $params['userid'];
3305 // Validate context.
3306 $context = context_system::instance();
3307 self::validate_context($context);
3309 // Check if private messaging between users is allowed.
3310 if (empty($CFG->messaging)) {
3311 throw new moodle_exception('disabled', 'message');
3314 $user = core_user::get_user($userid, '*', MUST_EXIST);
3315 core_user::require_active_user($user);
3317 // Check if we have permissions for retrieve the information.
3318 $capability = 'moodle/site:manageallmessaging';
3319 if (($USER->id != $userid) && !has_capability($capability, $context)) {
3320 throw new required_capability_exception($context, $capability, 'nopermissions', '');
3323 // Now, we can get safely all the blocked users.
3324 $users = \core_message\api::get_blocked_users($user->id);
3326 $blockedusers = array();
3327 foreach ($users as $user) {
3328 $newuser = array(
3329 'id' => $user->id,
3330 'fullname' => fullname($user),
3333 $userpicture = new user_picture($user);
3334 $userpicture->size = 1; // Size f1.
3335 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
3337 $blockedusers[] = $newuser;
3340 $results = array(
3341 'users' => $blockedusers,
3342 'warnings' => $warnings
3344 return $results;
3348 * Get blocked users return description.
3350 * @return external_single_structure
3351 * @since 2.9
3353 public static function get_blocked_users_returns() {
3354 return new external_single_structure(
3355 array(
3356 'users' => new external_multiple_structure(
3357 new external_single_structure(
3358 array(
3359 'id' => new external_value(PARAM_INT, 'User ID'),
3360 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
3361 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
3364 'List of blocked users'
3366 'warnings' => new external_warnings()
3372 * Returns description of method parameters
3374 * @return external_function_parameters
3375 * @since 2.9
3377 public static function mark_message_read_parameters() {
3378 return new external_function_parameters(
3379 array(
3380 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
3381 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
3382 VALUE_DEFAULT, 0)
3388 * Mark a single message as read, trigger message_viewed event
3390 * @param int $messageid id of the message (in the message table)
3391 * @param int $timeread timestamp for when the message should be marked read
3392 * @return external_description
3393 * @throws invalid_parameter_exception
3394 * @throws moodle_exception
3395 * @since 2.9
3397 public static function mark_message_read($messageid, $timeread) {
3398 global $CFG, $DB, $USER;
3400 // Check if private messaging between users is allowed.
3401 if (empty($CFG->messaging)) {
3402 throw new moodle_exception('disabled', 'message');
3405 // Warnings array, it can be empty at the end but is mandatory.
3406 $warnings = array();
3408 // Validate params.
3409 $params = array(
3410 'messageid' => $messageid,
3411 'timeread' => $timeread
3413 $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
3415 if (empty($params['timeread'])) {
3416 $timeread = time();
3417 } else {
3418 $timeread = $params['timeread'];
3421 // Validate context.
3422 $context = context_system::instance();
3423 self::validate_context($context);
3425 $sql = "SELECT m.*, mcm.userid as useridto
3426 FROM {messages} m
3427 INNER JOIN {message_conversations} mc
3428 ON m.conversationid = mc.id
3429 INNER JOIN {message_conversation_members} mcm
3430 ON mcm.conversationid = mc.id
3431 LEFT JOIN {message_user_actions} mua
3432 ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
3433 WHERE mua.id is NULL
3434 AND mcm.userid != m.useridfrom
3435 AND m.id = ?";
3436 $messageparams = [];
3437 $messageparams[] = $USER->id;
3438 $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
3439 $messageparams[] = $params['messageid'];
3440 $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
3442 if ($message->useridto != $USER->id) {
3443 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
3446 \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
3448 $results = array(
3449 'messageid' => $message->id,
3450 'warnings' => $warnings
3452 return $results;
3456 * Returns description of method result value
3458 * @return external_description
3459 * @since 2.9
3461 public static function mark_message_read_returns() {
3462 return new external_single_structure(
3463 array(
3464 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
3465 'warnings' => new external_warnings()
3471 * Returns description of method parameters
3473 * @return external_function_parameters
3475 public static function mark_notification_read_parameters() {
3476 return new external_function_parameters(
3477 array(
3478 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3479 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
3480 VALUE_DEFAULT, 0)
3486 * Mark a single notification as read.
3488 * This will trigger a 'notification_viewed' event.
3490 * @param int $notificationid id of the notification
3491 * @param int $timeread timestamp for when the notification should be marked read
3492 * @return external_description
3493 * @throws invalid_parameter_exception
3494 * @throws moodle_exception
3496 public static function mark_notification_read($notificationid, $timeread) {
3497 global $CFG, $DB, $USER;
3499 // Check if private messaging between users is allowed.
3500 if (empty($CFG->messaging)) {
3501 throw new moodle_exception('disabled', 'message');
3504 // Warnings array, it can be empty at the end but is mandatory.
3505 $warnings = array();
3507 // Validate params.
3508 $params = array(
3509 'notificationid' => $notificationid,
3510 'timeread' => $timeread
3512 $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
3514 if (empty($params['timeread'])) {
3515 $timeread = time();
3516 } else {
3517 $timeread = $params['timeread'];
3520 // Validate context.
3521 $context = context_system::instance();
3522 self::validate_context($context);
3524 $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
3526 if ($notification->useridto != $USER->id) {
3527 throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
3528 'notification as read');
3531 \core_message\api::mark_notification_as_read($notification, $timeread);
3533 $results = array(
3534 'notificationid' => $notification->id,
3535 'warnings' => $warnings
3538 return $results;
3542 * Returns description of method result value
3544 * @return external_description
3546 public static function mark_notification_read_returns() {
3547 return new external_single_structure(
3548 array(
3549 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3550 'warnings' => new external_warnings()
3556 * Mark all messages as read parameters description.
3558 * @deprecated since 3.6
3559 * @return external_function_parameters
3560 * @since 3.2
3562 public static function mark_all_messages_as_read_parameters() {
3563 return new external_function_parameters(
3564 array(
3565 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3566 'useridfrom' => new external_value(
3567 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3568 VALUE_DEFAULT, 0),
3574 * Mark all messages as read function.
3576 * @deprecated since 3.6
3577 * @throws invalid_parameter_exception
3578 * @throws moodle_exception
3579 * @param int $useridto the user id who received the message
3580 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
3581 * @return external_description
3582 * @since 3.2
3584 public static function mark_all_messages_as_read($useridto, $useridfrom) {
3585 global $USER, $CFG;
3587 // Check if messaging is enabled.
3588 if (empty($CFG->messaging)) {
3589 throw new moodle_exception('disabled', 'message');
3592 $params = self::validate_parameters(
3593 self::mark_all_messages_as_read_parameters(),
3594 array(
3595 'useridto' => $useridto,
3596 'useridfrom' => $useridfrom,
3600 $context = context_system::instance();
3601 self::validate_context($context);
3603 $useridto = $params['useridto'];
3604 $useridfrom = $params['useridfrom'];
3606 if (!empty($useridto)) {
3607 if (core_user::is_real_user($useridto)) {
3608 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3609 } else {
3610 throw new moodle_exception('invaliduser');
3614 if (!empty($useridfrom)) {
3615 // We use get_user here because the from user can be the noreply or support user.
3616 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3619 // Check if the current user is the sender/receiver or just a privileged user.
3620 if ($useridto != $USER->id and $useridfrom != $USER->id and
3621 // The deleteanymessage cap seems more reasonable here than readallmessages.
3622 !has_capability('moodle/site:deleteanymessage', $context)) {
3623 throw new moodle_exception('accessdenied', 'admin');
3626 if ($useridfrom) {
3627 if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
3628 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
3630 } else {
3631 \core_message\api::mark_all_messages_as_read($useridto);
3634 return true;
3638 * Mark all messages as read return description.
3640 * @deprecated since 3.6
3641 * @return external_single_structure
3642 * @since 3.2
3644 public static function mark_all_messages_as_read_returns() {
3645 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
3649 * Marking the method as deprecated.
3651 * @return bool
3653 public static function mark_all_messages_as_read_is_deprecated() {
3654 return true;
3658 * Mark all conversation messages as read parameters description.
3660 * @return external_function_parameters
3661 * @since 3.6
3663 public static function mark_all_conversation_messages_as_read_parameters() {
3664 return new external_function_parameters(
3665 array(
3666 'userid' => new external_value(PARAM_INT, 'The user id who who we are marking the messages as read for'),
3667 'conversationid' =>
3668 new external_value(PARAM_INT, 'The conversation id who who we are marking the messages as read for')
3674 * Mark all conversation messages as read function.
3676 * @param int $userid The user id of who we want to delete the conversation for
3677 * @param int $conversationid The id of the conversations
3678 * @since 3.6
3680 public static function mark_all_conversation_messages_as_read(int $userid, int $conversationid) {
3681 global $CFG;
3683 // Check if messaging is enabled.
3684 if (empty($CFG->messaging)) {
3685 throw new moodle_exception('disabled', 'message');
3688 $params = array(
3689 'userid' => $userid,
3690 'conversationid' => $conversationid,
3692 $params = self::validate_parameters(self::mark_all_conversation_messages_as_read_parameters(), $params);
3694 $context = context_system::instance();
3695 self::validate_context($context);
3697 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3698 core_user::require_active_user($user);
3700 if (\core_message\api::can_mark_all_messages_as_read($params['userid'], $params['conversationid'])) {
3701 \core_message\api::mark_all_messages_as_read($params['userid'], $params['conversationid']);
3702 } else {
3703 throw new moodle_exception('accessdenied', 'admin');
3708 * Mark all conversation messages as read return description.
3710 * @return external_warnings
3711 * @since 3.6
3713 public static function mark_all_conversation_messages_as_read_returns() {
3714 return null;
3718 * Returns description of method parameters.
3720 * @deprecated since 3.6
3721 * @return external_function_parameters
3722 * @since 3.2
3724 public static function delete_conversation_parameters() {
3725 return new external_function_parameters(
3726 array(
3727 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3728 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
3734 * Deletes a conversation.
3736 * @deprecated since 3.6
3737 * @param int $userid The user id of who we want to delete the conversation for
3738 * @param int $otheruserid The user id of the other user in the conversation
3739 * @return array
3740 * @throws moodle_exception
3741 * @since 3.2
3743 public static function delete_conversation($userid, $otheruserid) {
3744 global $CFG;
3746 // Check if private messaging between users is allowed.
3747 if (empty($CFG->messaging)) {
3748 throw new moodle_exception('disabled', 'message');
3751 // Warnings array, it can be empty at the end but is mandatory.
3752 $warnings = array();
3754 // Validate params.
3755 $params = array(
3756 'userid' => $userid,
3757 'otheruserid' => $otheruserid,
3759 $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
3761 // Validate context.
3762 $context = context_system::instance();
3763 self::validate_context($context);
3765 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3766 core_user::require_active_user($user);
3768 if (!$conversationid = \core_message\api::get_conversation_between_users([$params['userid'], $params['otheruserid']])) {
3769 return [];
3772 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3773 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3774 $status = true;
3775 } else {
3776 throw new moodle_exception('You do not have permission to delete messages');
3779 $results = array(
3780 'status' => $status,
3781 'warnings' => $warnings
3784 return $results;
3788 * Returns description of method result value.
3790 * @deprecated since 3.6
3791 * @return external_description
3792 * @since 3.2
3794 public static function delete_conversation_returns() {
3795 return new external_single_structure(
3796 array(
3797 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
3798 'warnings' => new external_warnings()
3804 * Marking the method as deprecated.
3806 * @return bool
3808 public static function delete_conversation_is_deprecated() {
3809 return true;
3813 * Returns description of method parameters.
3815 * @return external_function_parameters
3816 * @since 3.6
3818 public static function delete_conversations_by_id_parameters() {
3819 return new external_function_parameters(
3820 array(
3821 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3822 'conversationids' => new external_multiple_structure(
3823 new external_value(PARAM_INT, 'The id of the conversation'),
3824 'List of conversation IDs'
3831 * Deletes a conversation.
3833 * @param int $userid The user id of who we want to delete the conversation for
3834 * @param int[] $conversationids The ids of the conversations
3835 * @return array
3836 * @throws moodle_exception
3837 * @since 3.6
3839 public static function delete_conversations_by_id($userid, array $conversationids) {
3840 global $CFG;
3842 // Check if private messaging between users is allowed.
3843 if (empty($CFG->messaging)) {
3844 throw new moodle_exception('disabled', 'message');
3847 // Validate params.
3848 $params = [
3849 'userid' => $userid,
3850 'conversationids' => $conversationids,
3852 $params = self::validate_parameters(self::delete_conversations_by_id_parameters(), $params);
3854 // Validate context.
3855 $context = context_system::instance();
3856 self::validate_context($context);
3858 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3859 core_user::require_active_user($user);
3861 foreach ($params['conversationids'] as $conversationid) {
3862 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3863 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3864 } else {
3865 throw new moodle_exception("You do not have permission to delete the conversation '$conversationid'");
3869 return [];
3873 * Returns description of method result value.
3875 * @return external_description
3876 * @since 3.6
3878 public static function delete_conversations_by_id_returns() {
3879 return new external_warnings();
3883 * Returns description of method parameters
3885 * @return external_function_parameters
3886 * @since 3.1
3888 public static function delete_message_parameters() {
3889 return new external_function_parameters(
3890 array(
3891 'messageid' => new external_value(PARAM_INT, 'The message id'),
3892 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
3893 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
3899 * Deletes a message
3901 * @param int $messageid the message id
3902 * @param int $userid the user id of who we want to delete the message for
3903 * @param bool $read if is a message read (default to true)
3904 * @return external_description
3905 * @throws moodle_exception
3906 * @since 3.1
3908 public static function delete_message($messageid, $userid, $read = true) {
3909 global $CFG;
3911 // Check if private messaging between users is allowed.
3912 if (empty($CFG->messaging)) {
3913 throw new moodle_exception('disabled', 'message');
3916 // Warnings array, it can be empty at the end but is mandatory.
3917 $warnings = array();
3919 // Validate params.
3920 $params = array(
3921 'messageid' => $messageid,
3922 'userid' => $userid,
3923 'read' => $read
3925 $params = self::validate_parameters(self::delete_message_parameters(), $params);
3927 // Validate context.
3928 $context = context_system::instance();
3929 self::validate_context($context);
3931 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3932 core_user::require_active_user($user);
3934 if (\core_message\api::can_delete_message($user->id, $params['messageid'])) {
3935 $status = \core_message\api::delete_message($user->id, $params['messageid']);
3936 } else {
3937 throw new moodle_exception('You do not have permission to delete this message');
3940 $results = array(
3941 'status' => $status,
3942 'warnings' => $warnings
3944 return $results;
3948 * Returns description of method result value
3950 * @return external_description
3951 * @since 3.1
3953 public static function delete_message_returns() {
3954 return new external_single_structure(
3955 array(
3956 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
3957 'warnings' => new external_warnings()
3963 * Returns description of method parameters
3965 * @return external_function_parameters
3966 * @since 3.2
3968 public static function message_processor_config_form_parameters() {
3969 return new external_function_parameters(
3970 array(
3971 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
3972 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
3973 'formvalues' => new external_multiple_structure(
3974 new external_single_structure(
3975 array(
3976 'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
3977 'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
3980 'Config form values',
3981 VALUE_REQUIRED
3988 * Processes a message processor config form.
3990 * @param int $userid the user id
3991 * @param string $name the name of the processor
3992 * @param array $formvalues the form values
3993 * @return external_description
3994 * @throws moodle_exception
3995 * @since 3.2
3997 public static function message_processor_config_form($userid, $name, $formvalues) {
3998 global $USER, $CFG;
4000 // Check if messaging is enabled.
4001 if (empty($CFG->messaging)) {
4002 throw new moodle_exception('disabled', 'message');
4005 $params = self::validate_parameters(
4006 self::message_processor_config_form_parameters(),
4007 array(
4008 'userid' => $userid,
4009 'name' => $name,
4010 'formvalues' => $formvalues,
4014 $user = self::validate_preferences_permissions($params['userid']);
4016 $processor = get_message_processor($params['name']);
4017 $preferences = [];
4018 $form = new stdClass();
4020 foreach ($params['formvalues'] as $formvalue) {
4021 // Curly braces to ensure interpretation is consistent between
4022 // php 5 and php 7.
4023 $form->{$formvalue['name']} = $formvalue['value'];
4026 $processor->process_form($form, $preferences);
4028 if (!empty($preferences)) {
4029 set_user_preferences($preferences, $params['userid']);
4034 * Returns description of method result value
4036 * @return external_description
4037 * @since 3.2
4039 public static function message_processor_config_form_returns() {
4040 return null;
4044 * Returns description of method parameters
4046 * @return external_function_parameters
4047 * @since 3.2
4049 public static function get_message_processor_parameters() {
4050 return new external_function_parameters(
4051 array(
4052 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
4053 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
4059 * Get a message processor.
4061 * @param int $userid
4062 * @param string $name the name of the processor
4063 * @return external_description
4064 * @throws moodle_exception
4065 * @since 3.2
4067 public static function get_message_processor($userid = 0, $name) {
4068 global $USER, $PAGE, $CFG;
4070 // Check if messaging is enabled.
4071 if (empty($CFG->messaging)) {
4072 throw new moodle_exception('disabled', 'message');
4075 $params = self::validate_parameters(
4076 self::get_message_processor_parameters(),
4077 array(
4078 'userid' => $userid,
4079 'name' => $name,
4083 if (empty($params['userid'])) {
4084 $params['userid'] = $USER->id;
4087 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
4088 core_user::require_active_user($user);
4089 self::validate_context(context_user::instance($params['userid']));
4091 $processor = get_message_processor($params['name']);
4093 $processoroutput = new \core_message\output\processor($processor, $user);
4094 $renderer = $PAGE->get_renderer('core_message');
4096 return $processoroutput->export_for_template($renderer);
4100 * Returns description of method result value
4102 * @return external_description
4103 * @since 3.2
4105 public static function get_message_processor_returns() {
4106 return new external_function_parameters(
4107 array(
4108 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
4109 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
4115 * Check that the user has enough permission to retrieve message or notifications preferences.
4117 * @param int $userid the user id requesting the preferences
4118 * @return stdClass full user object
4119 * @throws moodle_exception
4120 * @since Moodle 3.2
4122 protected static function validate_preferences_permissions($userid) {
4123 global $USER;
4125 if (empty($userid)) {
4126 $user = $USER;
4127 } else {
4128 $user = core_user::get_user($userid, '*', MUST_EXIST);
4129 core_user::require_active_user($user);
4132 $systemcontext = context_system::instance();
4133 self::validate_context($systemcontext);
4135 // Check access control.
4136 if ($user->id == $USER->id) {
4137 // Editing own message profile.
4138 require_capability('moodle/user:editownmessageprofile', $systemcontext);
4139 } else {
4140 // Teachers, parents, etc.
4141 $personalcontext = context_user::instance($user->id);
4142 require_capability('moodle/user:editmessageprofile', $personalcontext);
4144 return $user;
4148 * Returns a notification or message preference structure.
4150 * @return external_single_structure the structure
4151 * @since Moodle 3.2
4153 protected static function get_preferences_structure() {
4154 return new external_single_structure(
4155 array(
4156 'userid' => new external_value(PARAM_INT, 'User id'),
4157 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
4158 'processors' => new external_multiple_structure(
4159 new external_single_structure(
4160 array(
4161 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
4162 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
4163 'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
4164 'contextid' => new external_value(PARAM_INT, 'Context id'),
4165 'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
4168 'Config form values'
4170 'components' => new external_multiple_structure(
4171 new external_single_structure(
4172 array(
4173 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
4174 'notifications' => new external_multiple_structure(
4175 new external_single_structure(
4176 array(
4177 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
4178 'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
4179 'processors' => new external_multiple_structure(
4180 new external_single_structure(
4181 array(
4182 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
4183 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
4184 'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
4185 'lockedmessage' => new external_value(PARAM_TEXT,
4186 'Text to display if locked', VALUE_OPTIONAL),
4187 'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
4188 'loggedin' => new external_single_structure(
4189 array(
4190 'name' => new external_value(PARAM_NOTAGS, 'Name'),
4191 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
4192 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
4195 'loggedoff' => new external_single_structure(
4196 array(
4197 'name' => new external_value(PARAM_NOTAGS, 'Name'),
4198 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
4199 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
4204 'Processors values for this notification'
4208 'List of notificaitons for the component'
4212 'Available components'
4219 * Returns description of method parameters
4221 * @return external_function_parameters
4222 * @since 3.2
4224 public static function get_user_notification_preferences_parameters() {
4225 return new external_function_parameters(
4226 array(
4227 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
4233 * Get the notification preferences for a given user.
4235 * @param int $userid id of the user, 0 for current user
4236 * @return external_description
4237 * @throws moodle_exception
4238 * @since 3.2
4240 public static function get_user_notification_preferences($userid = 0) {
4241 global $PAGE;
4243 $params = self::validate_parameters(
4244 self::get_user_notification_preferences_parameters(),
4245 array(
4246 'userid' => $userid,
4249 $user = self::validate_preferences_permissions($params['userid']);
4251 $processors = get_message_processors();
4252 $providers = message_get_providers_for_user($user->id);
4253 $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
4254 $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
4256 $renderer = $PAGE->get_renderer('core_message');
4258 $result = array(
4259 'warnings' => array(),
4260 'preferences' => $notificationlist->export_for_template($renderer)
4262 return $result;
4266 * Returns description of method result value
4268 * @return external_description
4269 * @since 3.2
4271 public static function get_user_notification_preferences_returns() {
4272 return new external_function_parameters(
4273 array(
4274 'preferences' => self::get_preferences_structure(),
4275 'warnings' => new external_warnings(),
4281 * Returns description of method parameters
4283 * @return external_function_parameters
4284 * @since 3.2
4286 public static function get_user_message_preferences_parameters() {
4287 return new external_function_parameters(
4288 array(
4289 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
4295 * Get the notification preferences for a given user.
4297 * @param int $userid id of the user, 0 for current user
4298 * @return external_description
4299 * @throws moodle_exception
4300 * @since 3.2
4302 public static function get_user_message_preferences($userid = 0) {
4303 global $CFG, $PAGE;
4305 $params = self::validate_parameters(
4306 self::get_user_message_preferences_parameters(),
4307 array(
4308 'userid' => $userid,
4312 $user = self::validate_preferences_permissions($params['userid']);
4314 // Filter out enabled, available system_configured and user_configured processors only.
4315 $readyprocessors = array_filter(get_message_processors(), function($processor) {
4316 return $processor->enabled &&
4317 $processor->configured &&
4318 $processor->object->is_user_configured() &&
4319 // Filter out processors that don't have and message preferences to configure.
4320 $processor->object->has_message_preferences();
4323 $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
4324 return $provider->component === 'moodle';
4326 $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
4327 $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
4328 $providers, $preferences, $user);
4330 $renderer = $PAGE->get_renderer('core_message');
4332 $entertosend = get_user_preferences('message_entertosend', $CFG->messagingdefaultpressenter, $user);
4334 $result = array(
4335 'warnings' => array(),
4336 'preferences' => $notificationlistoutput->export_for_template($renderer),
4337 'blocknoncontacts' => \core_message\api::get_user_privacy_messaging_preference($user->id),
4338 'entertosend' => $entertosend
4340 return $result;
4344 * Returns description of method result value
4346 * @return external_description
4347 * @since 3.2
4349 public static function get_user_message_preferences_returns() {
4350 return new external_function_parameters(
4351 array(
4352 'preferences' => self::get_preferences_structure(),
4353 'blocknoncontacts' => new external_value(PARAM_INT, 'Privacy messaging setting to define who can message you'),
4354 'entertosend' => new external_value(PARAM_BOOL, 'User preference for using enter to send messages'),
4355 'warnings' => new external_warnings(),
4361 * Returns description of method parameters for the favourite_conversations() method.
4363 * @return external_function_parameters
4365 public static function set_favourite_conversations_parameters() {
4366 return new external_function_parameters(
4367 array(
4368 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0),
4369 'conversations' => new external_multiple_structure(
4370 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0)
4377 * Favourite a conversation, or list of conversations for a user.
4379 * @param int $userid the id of the user, or 0 for the current user.
4380 * @param array $conversationids the list of conversations ids to favourite.
4381 * @return array
4382 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
4384 public static function set_favourite_conversations(int $userid, array $conversationids) {
4385 global $CFG, $USER;
4387 // All the business logic checks that really shouldn't be in here.
4388 if (empty($CFG->messaging)) {
4389 throw new moodle_exception('disabled', 'message');
4391 $params = [
4392 'userid' => $userid,
4393 'conversations' => $conversationids
4395 $params = self::validate_parameters(self::set_favourite_conversations_parameters(), $params);
4396 $systemcontext = context_system::instance();
4397 self::validate_context($systemcontext);
4399 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4400 throw new moodle_exception('You do not have permission to perform this action.');
4403 foreach ($params['conversations'] as $conversationid) {
4404 \core_message\api::set_favourite_conversation($conversationid, $params['userid']);
4407 return [];
4411 * Return a description of the returns for the create_user_favourite_conversations() method.
4413 * @return external_description
4415 public static function set_favourite_conversations_returns() {
4416 return new external_warnings();
4420 * Returns description of method parameters for unfavourite_conversations() method.
4422 * @return external_function_parameters
4424 public static function unset_favourite_conversations_parameters() {
4425 return new external_function_parameters(
4426 array(
4427 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0),
4428 'conversations' => new external_multiple_structure(
4429 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0)
4436 * Unfavourite a conversation, or list of conversations for a user.
4438 * @param int $userid the id of the user, or 0 for the current user.
4439 * @param array $conversationids the list of conversations ids unset as favourites.
4440 * @return array
4441 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
4443 public static function unset_favourite_conversations(int $userid, array $conversationids) {
4444 global $CFG, $USER;
4446 // All the business logic checks that really shouldn't be in here.
4447 if (empty($CFG->messaging)) {
4448 throw new moodle_exception('disabled', 'message');
4450 $params = [
4451 'userid' => $userid,
4452 'conversations' => $conversationids
4454 $params = self::validate_parameters(self::unset_favourite_conversations_parameters(), $params);
4455 $systemcontext = context_system::instance();
4456 self::validate_context($systemcontext);
4458 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4459 throw new moodle_exception('You do not have permission to perform this action.');
4462 foreach ($params['conversations'] as $conversationid) {
4463 \core_message\api::unset_favourite_conversation($conversationid, $params['userid']);
4466 return [];
4470 * Unset favourite conversations return description.
4472 * @return external_description
4474 public static function unset_favourite_conversations_returns() {
4475 return new external_warnings();
4479 * Returns description of method parameters for get_member_info() method.
4481 * @return external_function_parameters
4483 public static function get_member_info_parameters() {
4484 return new external_function_parameters(
4485 array(
4486 'referenceuserid' => new external_value(PARAM_INT, 'id of the user'),
4487 'userids' => new external_multiple_structure(
4488 new external_value(PARAM_INT, 'id of members to get')
4490 'includecontactrequests' => new external_value(PARAM_BOOL, 'include contact requests in response', VALUE_DEFAULT, false),
4491 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'include privacy info in response', VALUE_DEFAULT, false)
4497 * Returns conversation member info for the supplied users, relative to the supplied referenceuserid.
4499 * This is the basic structure used when returning members, and includes information about the relationship between each member
4500 * and the referenceuser, such as a whether the referenceuser has marked the member as a contact, or has blocked them.
4502 * @param int $referenceuserid the id of the user which check contact and blocked status.
4503 * @param array $userids
4504 * @return array the array of objects containing member info.
4505 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
4507 public static function get_member_info(
4508 int $referenceuserid,
4509 array $userids,
4510 bool $includecontactrequests = false,
4511 bool $includeprivacyinfo = false
4513 global $CFG, $USER;
4515 // All the business logic checks that really shouldn't be in here.
4516 if (empty($CFG->messaging)) {
4517 throw new moodle_exception('disabled', 'message');
4519 $params = [
4520 'referenceuserid' => $referenceuserid,
4521 'userids' => $userids,
4522 'includecontactrequests' => $includecontactrequests,
4523 'includeprivacyinfo' => $includeprivacyinfo
4525 $params = self::validate_parameters(self::get_member_info_parameters(), $params);
4526 $systemcontext = context_system::instance();
4527 self::validate_context($systemcontext);
4529 if (($USER->id != $referenceuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4530 throw new moodle_exception('You do not have permission to perform this action.');
4533 return \core_message\helper::get_member_info(
4534 $params['referenceuserid'],
4535 $params['userids'],
4536 $params['includecontactrequests'],
4537 $params['includeprivacyinfo']
4542 * Get member info return description.
4544 * @return external_description
4546 public static function get_member_info_returns() {
4547 return new external_multiple_structure(
4548 self::get_conversation_member_structure()
4553 * Returns description of method parameters for get_conversation_counts() method.
4555 * @return external_function_parameters
4557 public static function get_conversation_counts_parameters() {
4558 return new external_function_parameters(
4560 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
4566 * Returns an array of conversation counts for the various types of conversations, including favourites.
4568 * Return format:
4570 * 'favourites' => 0,
4571 * 'types' => [
4572 * \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
4573 * \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
4577 * @param int $userid the id of the user whose counts we are fetching.
4578 * @return array the array of conversation counts, indexed by type.
4579 * @throws moodle_exception if the current user cannot perform this action.
4581 public static function get_conversation_counts(int $userid) {
4582 global $CFG, $USER;
4584 // All the business logic checks that really shouldn't be in here.
4585 if (empty($CFG->messaging)) {
4586 throw new moodle_exception('disabled', 'message');
4589 if (empty($userid)) {
4590 $userid = $USER->id;
4593 $params = ['userid' => $userid];
4594 $params = self::validate_parameters(self::get_conversation_counts_parameters(), $params);
4596 $systemcontext = context_system::instance();
4597 self::validate_context($systemcontext);
4599 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4600 throw new moodle_exception('You do not have permission to perform this action.');
4603 return \core_message\api::get_conversation_counts($params['userid']);
4607 * Get conversation counts return description.
4609 * @return external_description
4611 public static function get_conversation_counts_returns() {
4612 return new external_single_structure(
4614 'favourites' => new external_value(PARAM_INT, 'Total number of favourite conversations'),
4615 'types' => new external_single_structure(
4617 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => new external_value(PARAM_INT,
4618 'Total number of individual conversations'),
4619 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => new external_value(PARAM_INT,
4620 'Total number of group conversations'),
4628 * Returns description of method parameters for get_unread_conversation_counts() method.
4630 * @return external_function_parameters
4632 public static function get_unread_conversation_counts_parameters() {
4633 return new external_function_parameters(
4635 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
4641 * Returns an array of unread conversation counts for the various types of conversations, including favourites.
4643 * Return format:
4645 * 'favourites' => 0,
4646 * 'types' => [
4647 * \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0,
4648 * \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0
4652 * @param int $userid the id of the user whose counts we are fetching.
4653 * @return array the array of unread conversation counts, indexed by type.
4654 * @throws moodle_exception if the current user cannot perform this action.
4656 public static function get_unread_conversation_counts(int $userid) {
4657 global $CFG, $USER;
4659 // All the business logic checks that really shouldn't be in here.
4660 if (empty($CFG->messaging)) {
4661 throw new moodle_exception('disabled', 'message');
4664 if (empty($userid)) {
4665 $userid = $USER->id;
4668 $params = ['userid' => $userid];
4669 $params = self::validate_parameters(self::get_unread_conversation_counts_parameters(), $params);
4671 $systemcontext = context_system::instance();
4672 self::validate_context($systemcontext);
4674 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
4675 throw new moodle_exception('You do not have permission to perform this action.');
4678 return \core_message\api::get_unread_conversation_counts($params['userid']);
4682 * Get unread conversation counts return description.
4684 * @return external_description
4686 public static function get_unread_conversation_counts_returns() {
4687 return new external_single_structure(
4689 'favourites' => new external_value(PARAM_INT, 'Total number of unread favourite conversations'),
4690 'types' => new external_single_structure(
4692 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => new external_value(PARAM_INT,
4693 'Total number of unread individual conversations'),
4694 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => new external_value(PARAM_INT,
4695 'Total number of unread group conversations'),