2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * External message API
21 * @package core_message
23 * @copyright 2011 Jerome Mouneyrac
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
29 require_once("$CFG->libdir/externallib.php");
30 require_once($CFG->dirroot . "/message/lib.php");
33 * Message external functions
35 * @package core_message
37 * @copyright 2011 Jerome Mouneyrac
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 class core_message_external extends external_api {
44 * Returns description of method parameters
46 * @return external_function_parameters
49 public static function send_instant_messages_parameters() {
50 return new external_function_parameters(
52 'messages' => new external_multiple_structure(
53 new external_single_structure(
55 'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
56 'text' => new external_value(PARAM_RAW, 'the text of the message'),
57 'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
58 '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),
67 * Send private messages from the current USER to other users
69 * @param array $messages An array of message to send.
73 public static function send_instant_messages($messages = array()) {
74 global $CFG, $USER, $DB;
76 // Check if messaging is enabled.
77 if (empty($CFG->messaging)) {
78 throw new moodle_exception('disabled', 'message');
81 // Ensure the current user is allowed to run this function
82 $context = context_system::instance();
83 self::validate_context($context);
84 require_capability('moodle/site:sendmessage', $context);
86 $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
88 //retrieve all tousers of the messages
90 foreach($params['messages'] as $message) {
91 $receivers[] = $message['touserid'];
93 list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers, SQL_PARAMS_NAMED, 'userid_');
94 $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
96 $contactlist = array();
97 $sqlparams['contactid'] = $USER->id;
98 $rs = $DB->get_recordset_sql("SELECT *
99 FROM {message_contacts}
100 WHERE userid $sqluserids
101 AND contactid = :contactid", $sqlparams);
102 foreach ($rs as $record) {
103 if ($record->blocked) {
104 // $record->userid is blocking current user
105 $blocklist[$record->userid] = true;
107 // $record->userid have current user as contact
108 $contactlist[$record->userid] = true;
113 $canreadallmessages = has_capability('moodle/site:readallmessages', $context);
115 $resultmessages = array();
116 foreach ($params['messages'] as $message) {
117 $resultmsg = array(); //the infos about the success of the operation
119 //we are going to do some checking
120 //code should match /messages/index.php checks
123 //check the user exists
124 if (empty($tousers[$message['touserid']])) {
126 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
129 //check that the touser is not blocking the current user
130 if ($success and !empty($blocklist[$message['touserid']]) and !$canreadallmessages) {
132 $errormessage = get_string('userisblockingyou', 'message');
135 // Check if the user is a contact
136 //TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
137 $blocknoncontacts = get_user_preferences('message_blocknoncontacts', NULL, $message['touserid']);
138 // message_blocknoncontacts option is on and current user is not in contact list
139 if ($success && empty($contactlist[$message['touserid']]) && !empty($blocknoncontacts)) {
140 // The user isn't a contact and they have selected to block non contacts so this message won't be sent.
142 $errormessage = get_string('userisblockingyounoncontact', 'message',
143 fullname(core_user::get_user($message['touserid'])));
146 //now we can send the message (at least try)
148 //TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object
149 $success = message_post_message($USER, $tousers[$message['touserid']],
150 $message['text'], external_validate_format($message['textformat']));
153 //build the resultmsg
154 if (isset($message['clientmsgid'])) {
155 $resultmsg['clientmsgid'] = $message['clientmsgid'];
158 $resultmsg['msgid'] = $success;
160 // WARNINGS: for backward compatibility we return this errormessage.
161 // We should have thrown exceptions as these errors prevent results to be returned.
162 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
163 $resultmsg['msgid'] = -1;
164 $resultmsg['errormessage'] = $errormessage;
167 $resultmessages[] = $resultmsg;
170 return $resultmessages;
174 * Returns description of method result value
176 * @return external_description
179 public static function send_instant_messages_returns() {
180 return new external_multiple_structure(
181 new external_single_structure(
183 'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds: id of the created message if it succeeded, -1 when failed'),
184 'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
185 'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL)
192 * Create contacts parameters description.
194 * @deprecated since Moodle 3.6
195 * @return external_function_parameters
198 public static function create_contacts_parameters() {
199 return new external_function_parameters(
201 'userids' => new external_multiple_structure(
202 new external_value(PARAM_INT, 'User ID'),
205 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
206 current user', VALUE_DEFAULT, 0)
214 * @deprecated since Moodle 3.6
215 * @param array $userids array of user IDs.
216 * @param int $userid The id of the user we are creating the contacts for
217 * @return external_description
220 public static function create_contacts($userids, $userid = 0) {
223 // Check if messaging is enabled.
224 if (empty($CFG->messaging)) {
225 throw new moodle_exception('disabled', 'message');
228 if (empty($userid)) {
233 $context = context_system::instance();
234 self::validate_context($context);
236 $capability = 'moodle/site:manageallmessaging';
237 if (($USER->id != $userid) && !has_capability($capability, $context)) {
238 throw new required_capability_exception($context, $capability, 'nopermissions', '');
241 $params = array('userids' => $userids, 'userid' => $userid);
242 $params = self::validate_parameters(self::create_contacts_parameters(), $params);
245 foreach ($params['userids'] as $id) {
246 if (!message_add_contact($id, 0, $userid)) {
250 'warningcode' => 'contactnotcreated',
251 'message' => 'The contact could not be created'
259 * Create contacts return description.
261 * @deprecated since Moodle 3.6
262 * @return external_description
265 public static function create_contacts_returns() {
266 return new external_warnings();
270 * Marking the method as deprecated.
274 public static function create_contacts_is_deprecated() {
279 * Delete contacts parameters description.
281 * @return external_function_parameters
284 public static function delete_contacts_parameters() {
285 return new external_function_parameters(
287 'userids' => new external_multiple_structure(
288 new external_value(PARAM_INT, 'User ID'),
291 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
292 current user', VALUE_DEFAULT, 0)
300 * @param array $userids array of user IDs.
301 * @param int $userid The id of the user we are deleting the contacts for
305 public static function delete_contacts($userids, $userid = 0) {
308 // Check if messaging is enabled.
309 if (empty($CFG->messaging)) {
310 throw new moodle_exception('disabled', 'message');
313 if (empty($userid)) {
318 $context = context_system::instance();
319 self::validate_context($context);
321 $capability = 'moodle/site:manageallmessaging';
322 if (($USER->id != $userid) && !has_capability($capability, $context)) {
323 throw new required_capability_exception($context, $capability, 'nopermissions', '');
326 $params = array('userids' => $userids, 'userid' => $userid);
327 $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
329 foreach ($params['userids'] as $id) {
330 message_remove_contact($id, $userid);
337 * Delete contacts return description.
339 * @return external_description
342 public static function delete_contacts_returns() {
347 * Block user parameters description.
349 * @return external_function_parameters
351 public static function block_user_parameters() {
352 return new external_function_parameters(
354 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
355 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
363 * @param int $userid The id of the user who is blocking
364 * @param int $blockeduserid The id of the user being blocked
365 * @return external_description
367 public static function block_user(int $userid, int $blockeduserid) {
370 // Check if messaging is enabled.
371 if (empty($CFG->messaging)) {
372 throw new moodle_exception('disabled', 'message');
376 $context = context_system::instance();
377 self::validate_context($context);
379 $capability = 'moodle/site:manageallmessaging';
380 if (($USER->id != $userid) && !has_capability($capability, $context)) {
381 throw new required_capability_exception($context, $capability, 'nopermissions', '');
384 $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
385 $params = self::validate_parameters(self::block_user_parameters(), $params);
387 if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
388 \core_message\api::block_user($params['userid'], $params['blockeduserid']);
395 * Block user return description.
397 * @return external_description
399 public static function block_user_returns() {
400 return new external_warnings();
404 * Unblock user parameters description.
406 * @return external_function_parameters
408 public static function unblock_user_parameters() {
409 return new external_function_parameters(
411 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
412 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
420 * @param int $userid The id of the user who is unblocking
421 * @param int $unblockeduserid The id of the user being unblocked
423 public static function unblock_user(int $userid, int $unblockeduserid) {
426 // Check if messaging is enabled.
427 if (empty($CFG->messaging)) {
428 throw new moodle_exception('disabled', 'message');
432 $context = context_system::instance();
433 self::validate_context($context);
435 $capability = 'moodle/site:manageallmessaging';
436 if (($USER->id != $userid) && !has_capability($capability, $context)) {
437 throw new required_capability_exception($context, $capability, 'nopermissions', '');
440 $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
441 $params = self::validate_parameters(self::unblock_user_parameters(), $params);
443 \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
449 * Unblock user return description.
451 * @return external_description
453 public static function unblock_user_returns() {
454 return new external_warnings();
458 * Block contacts parameters description.
460 * @deprecated since Moodle 3.6
461 * @return external_function_parameters
464 public static function block_contacts_parameters() {
465 return new external_function_parameters(
467 'userids' => new external_multiple_structure(
468 new external_value(PARAM_INT, 'User ID'),
471 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
472 current user', VALUE_DEFAULT, 0)
480 * @deprecated since Moodle 3.6
481 * @param array $userids array of user IDs.
482 * @param int $userid The id of the user we are blocking the contacts for
483 * @return external_description
486 public static function block_contacts($userids, $userid = 0) {
489 // Check if messaging is enabled.
490 if (empty($CFG->messaging)) {
491 throw new moodle_exception('disabled', 'message');
494 if (empty($userid)) {
499 $context = context_system::instance();
500 self::validate_context($context);
502 $capability = 'moodle/site:manageallmessaging';
503 if (($USER->id != $userid) && !has_capability($capability, $context)) {
504 throw new required_capability_exception($context, $capability, 'nopermissions', '');
507 $params = array('userids' => $userids, 'userid' => $userid);
508 $params = self::validate_parameters(self::block_contacts_parameters(), $params);
511 foreach ($params['userids'] as $id) {
512 if (!message_block_contact($id, $userid)) {
516 'warningcode' => 'contactnotblocked',
517 'message' => 'The contact could not be blocked'
525 * Block contacts return description.
527 * @deprecated since Moodle 3.6
528 * @return external_description
531 public static function block_contacts_returns() {
532 return new external_warnings();
536 * Marking the method as deprecated.
540 public static function block_contacts_is_deprecated() {
545 * Unblock contacts parameters description.
547 * @deprecated since Moodle 3.6
548 * @return external_function_parameters
551 public static function unblock_contacts_parameters() {
552 return new external_function_parameters(
554 'userids' => new external_multiple_structure(
555 new external_value(PARAM_INT, 'User ID'),
558 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
559 current user', VALUE_DEFAULT, 0)
567 * @deprecated since Moodle 3.6
568 * @param array $userids array of user IDs.
569 * @param int $userid The id of the user we are unblocking the contacts for
573 public static function unblock_contacts($userids, $userid = 0) {
576 // Check if messaging is enabled.
577 if (empty($CFG->messaging)) {
578 throw new moodle_exception('disabled', 'message');
581 if (empty($userid)) {
586 $context = context_system::instance();
587 self::validate_context($context);
589 $capability = 'moodle/site:manageallmessaging';
590 if (($USER->id != $userid) && !has_capability($capability, $context)) {
591 throw new required_capability_exception($context, $capability, 'nopermissions', '');
594 $params = array('userids' => $userids, 'userid' => $userid);
595 $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
597 foreach ($params['userids'] as $id) {
598 message_unblock_contact($id, $userid);
605 * Unblock contacts return description.
607 * @deprecated since Moodle 3.6
608 * @return external_description
611 public static function unblock_contacts_returns() {
616 * Marking the method as deprecated.
620 public static function unblock_contacts_is_deprecated() {
625 * Returns contact requests parameters description.
627 * @return external_function_parameters
629 public static function get_contact_requests_parameters() {
630 return new external_function_parameters(
632 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for')
638 * Handles returning the contact requests for a user.
640 * This also includes the user data necessary to display information
643 * It will not include blocked users.
645 * @param int $userid The id of the user we want to get the contact requests for
647 public static function get_contact_requests(int $userid) {
650 // Check if messaging is enabled.
651 if (empty($CFG->messaging)) {
652 throw new moodle_exception('disabled', 'message');
656 $context = context_system::instance();
657 self::validate_context($context);
659 $capability = 'moodle/site:manageallmessaging';
660 if (($USER->id != $userid) && !has_capability($capability, $context)) {
661 throw new required_capability_exception($context, $capability, 'nopermissions', '');
664 $params = ['userid' => $userid];
665 $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
667 return \core_message\api::get_contact_requests($params['userid']);
671 * Returns the contact requests return description.
673 * @return external_description
675 public static function get_contact_requests_returns() {
676 return new external_multiple_structure(
677 new external_single_structure(
679 'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'),
680 'contactrequestid' => new external_value(PARAM_INT, 'The ID of the contact request'),
681 'picture' => new external_value(core_user::get_property_type('picture'), 'The picture'),
682 'firstname' => new external_value(core_user::get_property_type('firstname'),
683 'The first name(s) of the user'),
684 'lastname' => new external_value(core_user::get_property_type('lastname'),
685 'The family name of the user'),
686 'firstnamephonetic' => new external_value(core_user::get_property_type('firstnamephonetic'),
687 'The phonetic first name of the user'),
688 'lastnamephonetic' => new external_value(core_user::get_property_type('lastnamephonetic'),
689 'The phonetic last name of the user'),
690 'middlename' => new external_value(core_user::get_property_type('middlename'),
691 'The middle name of the user'),
692 'alternatename' => new external_value(core_user::get_property_type('alternatename'),
693 'The alternate name of the user'),
694 'email' => new external_value(core_user::get_property_type('email'), 'An email address')
701 * Creates a contact request parameters description.
703 * @return external_function_parameters
705 public static function create_contact_request_parameters() {
706 return new external_function_parameters(
708 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
709 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
715 * Creates a contact request.
717 * @param int $userid The id of the user who is creating the contact request
718 * @param int $requesteduserid The id of the user being requested
720 public static function create_contact_request(int $userid, int $requesteduserid) {
723 // Check if messaging is enabled.
724 if (empty($CFG->messaging)) {
725 throw new moodle_exception('disabled', 'message');
729 $context = context_system::instance();
730 self::validate_context($context);
732 $capability = 'moodle/site:manageallmessaging';
733 if (($USER->id != $userid) && !has_capability($capability, $context)) {
734 throw new required_capability_exception($context, $capability, 'nopermissions', '');
737 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
738 $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
740 if (!\core_message\api::does_contact_request_exist($params['userid'], $params['requesteduserid'])) {
741 \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
748 * Creates a contact request return description.
750 * @return external_description
752 public static function create_contact_request_returns() {
753 return new external_warnings();
757 * Confirm a contact request parameters description.
759 * @return external_function_parameters
761 public static function confirm_contact_request_parameters() {
762 return new external_function_parameters(
764 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
765 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
771 * Confirm a contact request.
773 * @param int $userid The id of the user who is creating the contact request
774 * @param int $requesteduserid The id of the user being requested
776 public static function confirm_contact_request(int $userid, int $requesteduserid) {
779 // Check if messaging is enabled.
780 if (empty($CFG->messaging)) {
781 throw new moodle_exception('disabled', 'message');
785 $context = context_system::instance();
786 self::validate_context($context);
788 $capability = 'moodle/site:manageallmessaging';
789 if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
790 throw new required_capability_exception($context, $capability, 'nopermissions', '');
793 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
794 $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
796 \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
802 * Confirm a contact request return description.
804 * @return external_description
806 public static function confirm_contact_request_returns() {
807 return new external_warnings();
811 * Declines a contact request parameters description.
813 * @return external_function_parameters
815 public static function decline_contact_request_parameters() {
816 return new external_function_parameters(
818 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
819 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
825 * Declines a contact request.
827 * @param int $userid The id of the user who is creating the contact request
828 * @param int $requesteduserid The id of the user being requested
830 public static function decline_contact_request(int $userid, int $requesteduserid) {
833 // Check if messaging is enabled.
834 if (empty($CFG->messaging)) {
835 throw new moodle_exception('disabled', 'message');
839 $context = context_system::instance();
840 self::validate_context($context);
842 $capability = 'moodle/site:manageallmessaging';
843 if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
844 throw new required_capability_exception($context, $capability, 'nopermissions', '');
847 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
848 $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
850 \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
856 * Declines a contact request return description.
858 * @return external_description
860 public static function decline_contact_request_returns() {
861 return new external_warnings();
865 * Return the structure of a message area contact.
867 * @return external_single_structure
870 private static function get_messagearea_contact_structure() {
871 return new external_single_structure(
873 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
874 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
875 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
876 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
877 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
878 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
879 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
880 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
881 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
882 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
883 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
884 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
885 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
886 VALUE_DEFAULT, null),
892 * Return the structure of a message area message.
894 * @return external_single_structure
897 private static function get_messagearea_message_structure() {
898 return new external_single_structure(
900 'id' => new external_value(PARAM_INT, 'The id of the message'),
901 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
902 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
903 'text' => new external_value(PARAM_RAW, 'The text of the message'),
904 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
905 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
906 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
907 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
908 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
909 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
915 * Get messagearea search users in course parameters.
917 * @return external_function_parameters
920 public static function data_for_messagearea_search_users_in_course_parameters() {
921 return new external_function_parameters(
923 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
924 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
925 'search' => new external_value(PARAM_RAW, 'The string being searched'),
926 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
927 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
933 * Get messagearea search users in course results.
935 * @param int $userid The id of the user who is performing the search
936 * @param int $courseid The id of the course
937 * @param string $search The string being searched
938 * @param int $limitfrom
939 * @param int $limitnum
941 * @throws moodle_exception
944 public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
946 global $CFG, $PAGE, $USER;
948 // Check if messaging is enabled.
949 if (empty($CFG->messaging)) {
950 throw new moodle_exception('disabled', 'message');
953 $systemcontext = context_system::instance();
957 'courseid' => $courseid,
959 'limitfrom' => $limitfrom,
960 'limitnum' => $limitnum
962 self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
963 self::validate_context($systemcontext);
965 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
966 throw new moodle_exception('You do not have permission to perform this action.');
969 $users = \core_message\api::search_users_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
970 $results = new \core_message\output\messagearea\user_search_results($users);
972 $renderer = $PAGE->get_renderer('core_message');
973 return $results->export_for_template($renderer);
977 * Get messagearea search users in course returns.
979 * @return external_single_structure
982 public static function data_for_messagearea_search_users_in_course_returns() {
983 return new external_single_structure(
985 'contacts' => new external_multiple_structure(
986 self::get_messagearea_contact_structure()
993 * Get messagearea search users parameters.
995 * @return external_function_parameters
998 public static function data_for_messagearea_search_users_parameters() {
999 return new external_function_parameters(
1001 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1002 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1003 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1009 * Get messagearea search users results.
1011 * @param int $userid The id of the user who is performing the search
1012 * @param string $search The string being searched
1013 * @param int $limitnum
1015 * @throws moodle_exception
1018 public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1019 global $CFG, $PAGE, $USER;
1021 // Check if messaging is enabled.
1022 if (empty($CFG->messaging)) {
1023 throw new moodle_exception('disabled', 'message');
1026 $systemcontext = context_system::instance();
1029 'userid' => $userid,
1030 'search' => $search,
1031 'limitnum' => $limitnum
1033 self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1034 self::validate_context($systemcontext);
1036 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1037 throw new moodle_exception('You do not have permission to perform this action.');
1040 list($contacts, $courses, $noncontacts) = \core_message\api::search_users($userid, $search, $limitnum);
1041 $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1043 $renderer = $PAGE->get_renderer('core_message');
1044 return $search->export_for_template($renderer);
1048 * Get messagearea search users returns.
1050 * @return external_single_structure
1053 public static function data_for_messagearea_search_users_returns() {
1054 return new external_single_structure(
1056 'contacts' => new external_multiple_structure(
1057 self::get_messagearea_contact_structure()
1059 'courses' => new external_multiple_structure(
1060 new external_single_structure(
1062 'id' => new external_value(PARAM_INT, 'The course id'),
1063 'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1064 'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1068 'noncontacts' => new external_multiple_structure(
1069 self::get_messagearea_contact_structure()
1076 * Get messagearea search messages parameters.
1078 * @return external_function_parameters
1081 public static function data_for_messagearea_search_messages_parameters() {
1082 return new external_function_parameters(
1084 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1085 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1086 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1087 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1093 * Get messagearea search messages results.
1095 * @param int $userid The id of the user who is performing the search
1096 * @param string $search The string being searched
1097 * @param int $limitfrom
1098 * @param int $limitnum
1100 * @throws moodle_exception
1103 public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1104 global $CFG, $PAGE, $USER;
1106 // Check if messaging is enabled.
1107 if (empty($CFG->messaging)) {
1108 throw new moodle_exception('disabled', 'message');
1111 $systemcontext = context_system::instance();
1114 'userid' => $userid,
1115 'search' => $search,
1116 'limitfrom' => $limitfrom,
1117 'limitnum' => $limitnum
1120 self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1121 self::validate_context($systemcontext);
1123 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1124 throw new moodle_exception('You do not have permission to perform this action.');
1127 $messages = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
1128 $results = new \core_message\output\messagearea\message_search_results($messages);
1130 $renderer = $PAGE->get_renderer('core_message');
1131 return $results->export_for_template($renderer);
1135 * Get messagearea search messages returns.
1137 * @return external_single_structure
1140 public static function data_for_messagearea_search_messages_returns() {
1141 return new external_single_structure(
1143 'contacts' => new external_multiple_structure(
1144 self::get_messagearea_contact_structure()
1151 * The messagearea conversations parameters.
1153 * @return external_function_parameters
1156 public static function data_for_messagearea_conversations_parameters() {
1157 return new external_function_parameters(
1159 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1160 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1161 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1167 * Get messagearea conversations.
1169 * @param int $userid The id of the user who we are viewing conversations for
1170 * @param int $limitfrom
1171 * @param int $limitnum
1173 * @throws moodle_exception
1176 public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1177 global $CFG, $PAGE, $USER;
1179 // Check if messaging is enabled.
1180 if (empty($CFG->messaging)) {
1181 throw new moodle_exception('disabled', 'message');
1184 $systemcontext = context_system::instance();
1187 'userid' => $userid,
1188 'limitfrom' => $limitfrom,
1189 'limitnum' => $limitnum
1191 self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1192 self::validate_context($systemcontext);
1194 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1195 throw new moodle_exception('You do not have permission to perform this action.');
1198 $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum);
1199 $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1201 $renderer = $PAGE->get_renderer('core_message');
1202 return $conversations->export_for_template($renderer);
1206 * The messagearea conversations return structure.
1208 * @return external_single_structure
1211 public static function data_for_messagearea_conversations_returns() {
1212 return new external_single_structure(
1214 'contacts' => new external_multiple_structure(
1215 self::get_messagearea_contact_structure()
1222 * The messagearea contacts return parameters.
1224 * @return external_function_parameters
1227 public static function data_for_messagearea_contacts_parameters() {
1228 return self::data_for_messagearea_conversations_parameters();
1232 * Get messagearea contacts parameters.
1234 * @param int $userid The id of the user who we are viewing conversations for
1235 * @param int $limitfrom
1236 * @param int $limitnum
1238 * @throws moodle_exception
1241 public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1242 global $CFG, $PAGE, $USER;
1244 // Check if messaging is enabled.
1245 if (empty($CFG->messaging)) {
1246 throw new moodle_exception('disabled', 'message');
1249 $systemcontext = context_system::instance();
1252 'userid' => $userid,
1253 'limitfrom' => $limitfrom,
1254 'limitnum' => $limitnum
1256 self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1257 self::validate_context($systemcontext);
1259 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1260 throw new moodle_exception('You do not have permission to perform this action.');
1263 $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
1264 $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1266 $renderer = $PAGE->get_renderer('core_message');
1267 return $contacts->export_for_template($renderer);
1271 * The messagearea contacts return structure.
1273 * @return external_single_structure
1276 public static function data_for_messagearea_contacts_returns() {
1277 return self::data_for_messagearea_conversations_returns();
1281 * The messagearea messages parameters.
1283 * @return external_function_parameters
1286 public static function data_for_messagearea_messages_parameters() {
1287 return new external_function_parameters(
1289 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1290 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1291 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1292 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1293 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1294 'timefrom' => new external_value(PARAM_INT,
1295 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1301 * Get messagearea messages.
1303 * @param int $currentuserid The current user's id
1304 * @param int $otheruserid The other user's id
1305 * @param int $limitfrom
1306 * @param int $limitnum
1307 * @param boolean $newest
1309 * @throws moodle_exception
1312 public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
1313 $newest = false, $timefrom = 0) {
1314 global $CFG, $PAGE, $USER;
1316 // Check if messaging is enabled.
1317 if (empty($CFG->messaging)) {
1318 throw new moodle_exception('disabled', 'message');
1321 $systemcontext = context_system::instance();
1324 'currentuserid' => $currentuserid,
1325 'otheruserid' => $otheruserid,
1326 'limitfrom' => $limitfrom,
1327 'limitnum' => $limitnum,
1328 'newest' => $newest,
1329 'timefrom' => $timefrom,
1331 self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
1332 self::validate_context($systemcontext);
1334 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1335 throw new moodle_exception('You do not have permission to perform this action.');
1339 $sort = 'timecreated DESC';
1341 $sort = 'timecreated ASC';
1344 // We need to enforce a one second delay on messages to avoid race conditions of current
1345 // messages still being sent.
1347 // There is a chance that we could request messages before the current time's
1348 // second has elapsed and while other messages are being sent in that same second. In which
1349 // case those messages will be lost.
1351 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1352 if (!empty($timefrom)) {
1353 $timeto = time() - 1;
1358 // No requesting messages from the current time, as stated above.
1359 if ($timefrom == time()) {
1362 $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
1363 $limitnum, $sort, $timefrom, $timeto);
1366 $messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
1368 $renderer = $PAGE->get_renderer('core_message');
1369 return $messages->export_for_template($renderer);
1373 * The messagearea messages return structure.
1375 * @return external_single_structure
1378 public static function data_for_messagearea_messages_returns() {
1379 return new external_single_structure(
1381 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
1382 the messages on behalf of?'),
1383 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1384 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1385 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
1386 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1387 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1388 'messages' => new external_multiple_structure(
1389 self::get_messagearea_message_structure()
1391 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
1397 * The get most recent message return parameters.
1399 * @return external_function_parameters
1402 public static function data_for_messagearea_get_most_recent_message_parameters() {
1403 return new external_function_parameters(
1405 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1406 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1412 * Get the most recent message in a conversation.
1414 * @param int $currentuserid The current user's id
1415 * @param int $otheruserid The other user's id
1417 * @throws moodle_exception
1420 public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
1421 global $CFG, $PAGE, $USER;
1423 // Check if messaging is enabled.
1424 if (empty($CFG->messaging)) {
1425 throw new moodle_exception('disabled', 'message');
1428 $systemcontext = context_system::instance();
1431 'currentuserid' => $currentuserid,
1432 'otheruserid' => $otheruserid
1434 self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
1435 self::validate_context($systemcontext);
1437 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1438 throw new moodle_exception('You do not have permission to perform this action.');
1441 $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
1442 $message = new \core_message\output\messagearea\message($message);
1444 $renderer = $PAGE->get_renderer('core_message');
1445 return $message->export_for_template($renderer);
1449 * The get most recent message return structure.
1451 * @return external_single_structure
1454 public static function data_for_messagearea_get_most_recent_message_returns() {
1455 return self::get_messagearea_message_structure();
1459 * The get profile parameters.
1461 * @return external_function_parameters
1464 public static function data_for_messagearea_get_profile_parameters() {
1465 return new external_function_parameters(
1467 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1468 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
1474 * Get the profile information for a contact.
1476 * @param int $currentuserid The current user's id
1477 * @param int $otheruserid The id of the user whose profile we are viewing
1479 * @throws moodle_exception
1482 public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
1483 global $CFG, $PAGE, $USER;
1485 // Check if messaging is enabled.
1486 if (empty($CFG->messaging)) {
1487 throw new moodle_exception('disabled', 'message');
1490 $systemcontext = context_system::instance();
1493 'currentuserid' => $currentuserid,
1494 'otheruserid' => $otheruserid
1496 self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
1497 self::validate_context($systemcontext);
1499 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1500 throw new moodle_exception('You do not have permission to perform this action.');
1503 $profile = \core_message\api::get_profile($currentuserid, $otheruserid);
1504 $profile = new \core_message\output\messagearea\profile($profile);
1506 $renderer = $PAGE->get_renderer('core_message');
1507 return $profile->export_for_template($renderer);
1511 * The get profile return structure.
1513 * @return external_single_structure
1516 public static function data_for_messagearea_get_profile_returns() {
1517 return new external_single_structure(
1519 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
1520 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
1521 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
1522 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
1523 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1524 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1525 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1526 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1527 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1528 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
1529 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
1535 * Get contacts parameters description.
1537 * @return external_function_parameters
1540 public static function get_contacts_parameters() {
1541 return new external_function_parameters(array());
1547 * @return external_description
1550 public static function get_contacts() {
1551 global $CFG, $PAGE, $USER;
1553 // Check if messaging is enabled.
1554 if (empty($CFG->messaging)) {
1555 throw new moodle_exception('disabled', 'message');
1558 require_once($CFG->dirroot . '/user/lib.php');
1560 $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
1561 $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
1562 foreach ($contacts as $contact) {
1565 if (\core_message\helper::is_online($contact->lastaccess)) {
1569 $newcontact = array(
1570 'id' => $contact->id,
1571 'fullname' => fullname($contact),
1572 'unread' => $contact->messagecount
1575 $userpicture = new user_picture($contact);
1576 $userpicture->size = 1; // Size f1.
1577 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1578 $userpicture->size = 0; // Size f2.
1579 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1581 $allcontacts[$mode][$contact->id] = $newcontact;
1584 $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
1585 foreach ($strangers as $contact) {
1586 $newcontact = array(
1587 'id' => $contact->id,
1588 'fullname' => fullname($contact),
1589 'unread' => $contact->messagecount
1592 $userpicture = new user_picture($contact);
1593 $userpicture->size = 1; // Size f1.
1594 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1595 $userpicture->size = 0; // Size f2.
1596 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1598 $allcontacts['strangers'][$contact->id] = $newcontact;
1601 // Add noreply user and support user to the list, if they don't exist.
1602 $supportuser = core_user::get_support_user();
1603 if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
1604 $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
1605 if ($supportuser->messagecount > 0) {
1606 $supportuser->fullname = fullname($supportuser);
1607 $supportuser->unread = $supportuser->messagecount;
1608 $allcontacts['strangers'][$supportuser->id] = $supportuser;
1612 $noreplyuser = core_user::get_noreply_user();
1613 if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
1614 $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
1615 if ($noreplyuser->messagecount > 0) {
1616 $noreplyuser->fullname = fullname($noreplyuser);
1617 $noreplyuser->unread = $noreplyuser->messagecount;
1618 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
1622 return $allcontacts;
1626 * Get contacts return description.
1628 * @return external_description
1631 public static function get_contacts_returns() {
1632 return new external_single_structure(
1634 'online' => new external_multiple_structure(
1635 new external_single_structure(
1637 'id' => new external_value(PARAM_INT, 'User ID'),
1638 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1639 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1640 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1641 'unread' => new external_value(PARAM_INT, 'Unread message count')
1644 'List of online contacts'
1646 'offline' => new external_multiple_structure(
1647 new external_single_structure(
1649 'id' => new external_value(PARAM_INT, 'User ID'),
1650 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1651 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1652 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1653 'unread' => new external_value(PARAM_INT, 'Unread message count')
1656 'List of offline contacts'
1658 'strangers' => new external_multiple_structure(
1659 new external_single_structure(
1661 'id' => new external_value(PARAM_INT, 'User ID'),
1662 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1663 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1664 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1665 'unread' => new external_value(PARAM_INT, 'Unread message count')
1668 'List of users that are not in the user\'s contact list but have sent a message'
1675 * Search contacts parameters description.
1677 * @return external_function_parameters
1680 public static function search_contacts_parameters() {
1681 return new external_function_parameters(
1683 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
1684 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
1685 VALUE_DEFAULT, false)
1693 * @param string $searchtext query string.
1694 * @param bool $onlymycourses limit the search to the user's courses only.
1695 * @return external_description
1698 public static function search_contacts($searchtext, $onlymycourses = false) {
1699 global $CFG, $USER, $PAGE;
1700 require_once($CFG->dirroot . '/user/lib.php');
1702 // Check if messaging is enabled.
1703 if (empty($CFG->messaging)) {
1704 throw new moodle_exception('disabled', 'message');
1707 require_once($CFG->libdir . '/enrollib.php');
1709 $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
1710 $params = self::validate_parameters(self::search_contacts_parameters(), $params);
1712 // Extra validation, we do not allow empty queries.
1713 if ($params['searchtext'] === '') {
1714 throw new moodle_exception('querystringcannotbeempty');
1717 $courseids = array();
1718 if ($params['onlymycourses']) {
1719 $mycourses = enrol_get_my_courses(array('id'));
1720 foreach ($mycourses as $mycourse) {
1721 $courseids[] = $mycourse->id;
1724 $courseids[] = SITEID;
1727 // Retrieving the users matching the query.
1728 $users = message_search_users($courseids, $params['searchtext']);
1730 foreach ($users as $user) {
1731 $results[$user->id] = $user;
1734 // Reorganising information.
1735 foreach ($results as &$user) {
1738 'fullname' => fullname($user)
1741 // Avoid undefined property notice as phone not specified.
1742 $user->phone1 = null;
1743 $user->phone2 = null;
1745 $userpicture = new user_picture($user);
1746 $userpicture->size = 1; // Size f1.
1747 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1748 $userpicture->size = 0; // Size f2.
1749 $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1758 * Search contacts return description.
1760 * @return external_description
1763 public static function search_contacts_returns() {
1764 return new external_multiple_structure(
1765 new external_single_structure(
1767 'id' => new external_value(PARAM_INT, 'User ID'),
1768 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1769 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1770 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
1778 * Get messages parameters description.
1780 * @return external_function_parameters
1783 public static function get_messages_parameters() {
1784 return new external_function_parameters(
1786 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1787 'useridfrom' => new external_value(
1788 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1790 'type' => new external_value(
1791 PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
1792 VALUE_DEFAULT, 'both'),
1793 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
1794 'newestfirst' => new external_value(
1795 PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
1796 VALUE_DEFAULT, true),
1797 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
1798 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
1804 * Get messages function implementation.
1807 * @throws invalid_parameter_exception
1808 * @throws moodle_exception
1809 * @param int $useridto the user id who received the message
1810 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
1811 * @param string $type type of message to return, expected values: notifications, conversations and both
1812 * @param bool $read true for retreiving read messages, false for unread
1813 * @param bool $newestfirst true for ordering by newest first, false for oldest first
1814 * @param int $limitfrom limit from
1815 * @param int $limitnum limit num
1816 * @return external_description
1818 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
1819 $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
1822 $warnings = array();
1825 'useridto' => $useridto,
1826 'useridfrom' => $useridfrom,
1829 'newestfirst' => $newestfirst,
1830 'limitfrom' => $limitfrom,
1831 'limitnum' => $limitnum
1834 $params = self::validate_parameters(self::get_messages_parameters(), $params);
1836 $context = context_system::instance();
1837 self::validate_context($context);
1839 $useridto = $params['useridto'];
1840 $useridfrom = $params['useridfrom'];
1841 $type = $params['type'];
1842 $read = $params['read'];
1843 $newestfirst = $params['newestfirst'];
1844 $limitfrom = $params['limitfrom'];
1845 $limitnum = $params['limitnum'];
1847 $allowedvalues = array('notifications', 'conversations', 'both');
1848 if (!in_array($type, $allowedvalues)) {
1849 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
1850 'allowed values are: ' . implode(',', $allowedvalues));
1853 // Check if private messaging between users is allowed.
1854 if (empty($CFG->messaging)) {
1855 // If we are retreiving only conversations, and messaging is disabled, throw an exception.
1856 if ($type == "conversations") {
1857 throw new moodle_exception('disabled', 'message');
1859 if ($type == "both") {
1861 $warning['item'] = 'message';
1862 $warning['itemid'] = $USER->id;
1863 $warning['warningcode'] = '1';
1864 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
1865 Only notifications will be returned';
1866 $warnings[] = $warning;
1870 if (!empty($useridto)) {
1871 if (core_user::is_real_user($useridto)) {
1872 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1874 throw new moodle_exception('invaliduser');
1878 if (!empty($useridfrom)) {
1879 // We use get_user here because the from user can be the noreply or support user.
1880 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1883 // Check if the current user is the sender/receiver or just a privileged user.
1884 if ($useridto != $USER->id and $useridfrom != $USER->id and
1885 !has_capability('moodle/site:readallmessages', $context)) {
1886 throw new moodle_exception('accessdenied', 'admin');
1889 // Which type of messages to retrieve.
1890 $notifications = -1;
1891 if ($type != 'both') {
1892 $notifications = ($type == 'notifications') ? 1 : 0;
1895 $orderdirection = $newestfirst ? 'DESC' : 'ASC';
1896 $sort = "mr.timecreated $orderdirection";
1898 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
1899 $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
1901 // In some cases, we don't need to get the to/from user objects from the sql query.
1902 $userfromfullname = '';
1903 $usertofullname = '';
1905 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
1906 if (!empty($useridto)) {
1907 $usertofullname = fullname($userto, $canviewfullname);
1908 // The user from may or may not be filled.
1909 if (!empty($useridfrom)) {
1910 $userfromfullname = fullname($userfrom, $canviewfullname);
1913 // If the useridto field is empty, the useridfrom must be filled.
1914 $userfromfullname = fullname($userfrom, $canviewfullname);
1916 foreach ($messages as $mid => $message) {
1918 // Do not return deleted messages.
1919 if (!$message->notification) {
1920 if (($useridto == $USER->id and $message->timeusertodeleted) or
1921 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
1922 unset($messages[$mid]);
1927 // We need to get the user from the query.
1928 if (empty($userfromfullname)) {
1929 // Check for non-reply and support users.
1930 if (core_user::is_real_user($message->useridfrom)) {
1931 $user = new stdClass();
1932 $user = username_load_fields_from_object($user, $message, 'userfrom');
1933 $message->userfromfullname = fullname($user, $canviewfullname);
1935 $user = core_user::get_user($message->useridfrom);
1936 $message->userfromfullname = fullname($user, $canviewfullname);
1939 $message->userfromfullname = $userfromfullname;
1942 // We need to get the user from the query.
1943 if (empty($usertofullname)) {
1944 $user = new stdClass();
1945 $user = username_load_fields_from_object($user, $message, 'userto');
1946 $message->usertofullname = fullname($user, $canviewfullname);
1948 $message->usertofullname = $usertofullname;
1951 $message->text = message_format_message_text($message);
1952 $messages[$mid] = (array) $message;
1957 'messages' => $messages,
1958 'warnings' => $warnings
1965 * Get messages return description.
1967 * @return external_single_structure
1970 public static function get_messages_returns() {
1971 return new external_single_structure(
1973 'messages' => new external_multiple_structure(
1974 new external_single_structure(
1976 'id' => new external_value(PARAM_INT, 'Message id'),
1977 'useridfrom' => new external_value(PARAM_INT, 'User from id'),
1978 'useridto' => new external_value(PARAM_INT, 'User to id'),
1979 'subject' => new external_value(PARAM_TEXT, 'The message subject'),
1980 'text' => new external_value(PARAM_RAW, 'The message text formated'),
1981 'fullmessage' => new external_value(PARAM_RAW, 'The message'),
1982 'fullmessageformat' => new external_format_value('fullmessage'),
1983 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
1984 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
1985 'notification' => new external_value(PARAM_INT, 'Is a notification?'),
1986 'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
1987 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
1988 'timecreated' => new external_value(PARAM_INT, 'Time created'),
1989 'timeread' => new external_value(PARAM_INT, 'Time read'),
1990 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
1991 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
1995 'warnings' => new external_warnings()
2001 * Mark all notifications as read parameters description.
2003 * @return external_function_parameters
2006 public static function mark_all_notifications_as_read_parameters() {
2007 return new external_function_parameters(
2009 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2010 'useridfrom' => new external_value(
2011 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2018 * Mark all notifications as read function.
2021 * @throws invalid_parameter_exception
2022 * @throws moodle_exception
2023 * @param int $useridto the user id who received the message
2024 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2025 * @return external_description
2027 public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2030 $params = self::validate_parameters(
2031 self::mark_all_notifications_as_read_parameters(),
2033 'useridto' => $useridto,
2034 'useridfrom' => $useridfrom,
2038 $context = context_system::instance();
2039 self::validate_context($context);
2041 $useridto = $params['useridto'];
2042 $useridfrom = $params['useridfrom'];
2044 if (!empty($useridto)) {
2045 if (core_user::is_real_user($useridto)) {
2046 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2048 throw new moodle_exception('invaliduser');
2052 if (!empty($useridfrom)) {
2053 // We use get_user here because the from user can be the noreply or support user.
2054 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2057 // Check if the current user is the sender/receiver or just a privileged user.
2058 if ($useridto != $USER->id and $useridfrom != $USER->id and
2059 // The deleteanymessage cap seems more reasonable here than readallmessages.
2060 !has_capability('moodle/site:deleteanymessage', $context)) {
2061 throw new moodle_exception('accessdenied', 'admin');
2064 \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2070 * Mark all notifications as read return description.
2072 * @return external_single_structure
2075 public static function mark_all_notifications_as_read_returns() {
2076 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2080 * Get unread conversations count parameters description.
2082 * @return external_function_parameters
2085 public static function get_unread_conversations_count_parameters() {
2086 return new external_function_parameters(
2088 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2094 * Get unread messages count function.
2097 * @throws invalid_parameter_exception
2098 * @throws moodle_exception
2099 * @param int $useridto the user id who received the message
2100 * @return external_description
2102 public static function get_unread_conversations_count($useridto) {
2105 // Check if messaging is enabled.
2106 if (empty($CFG->messaging)) {
2107 throw new moodle_exception('disabled', 'message');
2110 $params = self::validate_parameters(
2111 self::get_unread_conversations_count_parameters(),
2112 array('useridto' => $useridto)
2115 $context = context_system::instance();
2116 self::validate_context($context);
2118 $useridto = $params['useridto'];
2120 if (!empty($useridto)) {
2121 if (core_user::is_real_user($useridto)) {
2122 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2124 throw new moodle_exception('invaliduser');
2127 $useridto = $USER->id;
2130 // Check if the current user is the receiver or just a privileged user.
2131 if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2132 throw new moodle_exception('accessdenied', 'admin');
2135 return \core_message\api::count_unread_conversations($userto);
2139 * Get unread conversations count return description.
2141 * @return external_single_structure
2144 public static function get_unread_conversations_count_returns() {
2145 return new external_value(PARAM_INT, 'The count of unread messages for the user');
2149 * Get blocked users parameters description.
2151 * @return external_function_parameters
2154 public static function get_blocked_users_parameters() {
2155 return new external_function_parameters(
2157 'userid' => new external_value(PARAM_INT,
2158 'the user whose blocked users we want to retrieve',
2165 * Retrieve a list of users blocked
2167 * @param int $userid the user whose blocked users we want to retrieve
2168 * @return external_description
2171 public static function get_blocked_users($userid) {
2172 global $CFG, $USER, $PAGE;
2174 // Warnings array, it can be empty at the end but is mandatory.
2175 $warnings = array();
2181 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
2182 $userid = $params['userid'];
2184 // Validate context.
2185 $context = context_system::instance();
2186 self::validate_context($context);
2188 // Check if private messaging between users is allowed.
2189 if (empty($CFG->messaging)) {
2190 throw new moodle_exception('disabled', 'message');
2193 $user = core_user::get_user($userid, '*', MUST_EXIST);
2194 core_user::require_active_user($user);
2196 // Check if we have permissions for retrieve the information.
2197 $capability = 'moodle/site:manageallmessaging';
2198 if (($USER->id != $userid) && !has_capability($capability, $context)) {
2199 throw new required_capability_exception($context, $capability, 'nopermissions', '');
2202 // Now, we can get safely all the blocked users.
2203 $users = \core_message\api::get_blocked_users($user->id);
2205 $blockedusers = array();
2206 foreach ($users as $user) {
2209 'fullname' => fullname($user),
2212 $userpicture = new user_picture($user);
2213 $userpicture->size = 1; // Size f1.
2214 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2216 $blockedusers[] = $newuser;
2220 'users' => $blockedusers,
2221 'warnings' => $warnings
2227 * Get blocked users return description.
2229 * @return external_single_structure
2232 public static function get_blocked_users_returns() {
2233 return new external_single_structure(
2235 'users' => new external_multiple_structure(
2236 new external_single_structure(
2238 'id' => new external_value(PARAM_INT, 'User ID'),
2239 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2240 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
2243 'List of blocked users'
2245 'warnings' => new external_warnings()
2251 * Returns description of method parameters
2253 * @return external_function_parameters
2256 public static function mark_message_read_parameters() {
2257 return new external_function_parameters(
2259 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
2260 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
2267 * Mark a single message as read, trigger message_viewed event
2269 * @param int $messageid id of the message (in the message table)
2270 * @param int $timeread timestamp for when the message should be marked read
2271 * @return external_description
2272 * @throws invalid_parameter_exception
2273 * @throws moodle_exception
2276 public static function mark_message_read($messageid, $timeread) {
2277 global $CFG, $DB, $USER;
2279 // Check if private messaging between users is allowed.
2280 if (empty($CFG->messaging)) {
2281 throw new moodle_exception('disabled', 'message');
2284 // Warnings array, it can be empty at the end but is mandatory.
2285 $warnings = array();
2289 'messageid' => $messageid,
2290 'timeread' => $timeread
2292 $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
2294 if (empty($params['timeread'])) {
2297 $timeread = $params['timeread'];
2300 // Validate context.
2301 $context = context_system::instance();
2302 self::validate_context($context);
2304 $sql = "SELECT m.*, mcm.userid as useridto
2306 INNER JOIN {message_conversations} mc
2307 ON m.conversationid = mc.id
2308 INNER JOIN {message_conversation_members} mcm
2309 ON mcm.conversationid = mc.id
2310 LEFT JOIN {message_user_actions} mua
2311 ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
2312 WHERE mua.id is NULL
2313 AND mcm.userid != m.useridfrom
2315 $messageparams = [];
2316 $messageparams[] = $USER->id;
2317 $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
2318 $messageparams[] = $params['messageid'];
2319 $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
2321 if ($message->useridto != $USER->id) {
2322 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
2325 \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
2328 'messageid' => $message->id,
2329 'warnings' => $warnings
2335 * Returns description of method result value
2337 * @return external_description
2340 public static function mark_message_read_returns() {
2341 return new external_single_structure(
2343 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
2344 'warnings' => new external_warnings()
2350 * Returns description of method parameters
2352 * @return external_function_parameters
2354 public static function mark_notification_read_parameters() {
2355 return new external_function_parameters(
2357 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2358 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
2365 * Mark a single notification as read.
2367 * This will trigger a 'notification_viewed' event.
2369 * @param int $notificationid id of the notification
2370 * @param int $timeread timestamp for when the notification should be marked read
2371 * @return external_description
2372 * @throws invalid_parameter_exception
2373 * @throws moodle_exception
2375 public static function mark_notification_read($notificationid, $timeread) {
2376 global $CFG, $DB, $USER;
2378 // Check if private messaging between users is allowed.
2379 if (empty($CFG->messaging)) {
2380 throw new moodle_exception('disabled', 'message');
2383 // Warnings array, it can be empty at the end but is mandatory.
2384 $warnings = array();
2388 'notificationid' => $notificationid,
2389 'timeread' => $timeread
2391 $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
2393 if (empty($params['timeread'])) {
2396 $timeread = $params['timeread'];
2399 // Validate context.
2400 $context = context_system::instance();
2401 self::validate_context($context);
2403 $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
2405 if ($notification->useridto != $USER->id) {
2406 throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
2407 'notification as read');
2410 \core_message\api::mark_notification_as_read($notification, $timeread);
2413 'notificationid' => $notification->id,
2414 'warnings' => $warnings
2421 * Returns description of method result value
2423 * @return external_description
2425 public static function mark_notification_read_returns() {
2426 return new external_single_structure(
2428 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2429 'warnings' => new external_warnings()
2435 * Mark all messages as read parameters description.
2437 * @return external_function_parameters
2440 public static function mark_all_messages_as_read_parameters() {
2441 return new external_function_parameters(
2443 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2444 'useridfrom' => new external_value(
2445 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2452 * Mark all notifications as read function.
2455 * @throws invalid_parameter_exception
2456 * @throws moodle_exception
2457 * @param int $useridto the user id who received the message
2458 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2459 * @return external_description
2461 public static function mark_all_messages_as_read($useridto, $useridfrom) {
2464 // Check if messaging is enabled.
2465 if (empty($CFG->messaging)) {
2466 throw new moodle_exception('disabled', 'message');
2469 $params = self::validate_parameters(
2470 self::mark_all_messages_as_read_parameters(),
2472 'useridto' => $useridto,
2473 'useridfrom' => $useridfrom,
2477 $context = context_system::instance();
2478 self::validate_context($context);
2480 $useridto = $params['useridto'];
2481 $useridfrom = $params['useridfrom'];
2483 if (!empty($useridto)) {
2484 if (core_user::is_real_user($useridto)) {
2485 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2487 throw new moodle_exception('invaliduser');
2491 if (!empty($useridfrom)) {
2492 // We use get_user here because the from user can be the noreply or support user.
2493 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2496 // Check if the current user is the sender/receiver or just a privileged user.
2497 if ($useridto != $USER->id and $useridfrom != $USER->id and
2498 // The deleteanymessage cap seems more reasonable here than readallmessages.
2499 !has_capability('moodle/site:deleteanymessage', $context)) {
2500 throw new moodle_exception('accessdenied', 'admin');
2504 if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
2505 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
2508 \core_message\api::mark_all_messages_as_read($useridto);
2515 * Mark all notifications as read return description.
2517 * @return external_single_structure
2520 public static function mark_all_messages_as_read_returns() {
2521 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2525 * Returns description of method parameters.
2527 * @return external_function_parameters
2530 public static function delete_conversation_parameters() {
2531 return new external_function_parameters(
2533 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
2534 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
2540 * Deletes a conversation.
2542 * @param int $userid The user id of who we want to delete the conversation for
2543 * @param int $otheruserid The user id of the other user in the conversation
2545 * @throws moodle_exception
2548 public static function delete_conversation($userid, $otheruserid) {
2551 // Check if private messaging between users is allowed.
2552 if (empty($CFG->messaging)) {
2553 throw new moodle_exception('disabled', 'message');
2556 // Warnings array, it can be empty at the end but is mandatory.
2557 $warnings = array();
2561 'userid' => $userid,
2562 'otheruserid' => $otheruserid,
2564 $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
2566 // Validate context.
2567 $context = context_system::instance();
2568 self::validate_context($context);
2570 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2571 core_user::require_active_user($user);
2573 if (\core_message\api::can_delete_conversation($user->id)) {
2574 $status = \core_message\api::delete_conversation($user->id, $otheruserid);
2576 throw new moodle_exception('You do not have permission to delete messages');
2580 'status' => $status,
2581 'warnings' => $warnings
2588 * Returns description of method result value.
2590 * @return external_description
2593 public static function delete_conversation_returns() {
2594 return new external_single_structure(
2596 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
2597 'warnings' => new external_warnings()
2603 * Returns description of method parameters
2605 * @return external_function_parameters
2608 public static function delete_message_parameters() {
2609 return new external_function_parameters(
2611 'messageid' => new external_value(PARAM_INT, 'The message id'),
2612 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
2613 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
2621 * @param int $messageid the message id
2622 * @param int $userid the user id of who we want to delete the message for
2623 * @param bool $read if is a message read (default to true)
2624 * @return external_description
2625 * @throws moodle_exception
2628 public static function delete_message($messageid, $userid, $read = true) {
2631 // Check if private messaging between users is allowed.
2632 if (empty($CFG->messaging)) {
2633 throw new moodle_exception('disabled', 'message');
2636 // Warnings array, it can be empty at the end but is mandatory.
2637 $warnings = array();
2641 'messageid' => $messageid,
2642 'userid' => $userid,
2645 $params = self::validate_parameters(self::delete_message_parameters(), $params);
2647 // Validate context.
2648 $context = context_system::instance();
2649 self::validate_context($context);
2651 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2652 core_user::require_active_user($user);
2654 if (\core_message\api::can_delete_message($user->id, $messageid)) {
2655 $status = \core_message\api::delete_message($user->id, $messageid);
2657 throw new moodle_exception('You do not have permission to delete this message');
2661 'status' => $status,
2662 'warnings' => $warnings
2668 * Returns description of method result value
2670 * @return external_description
2673 public static function delete_message_returns() {
2674 return new external_single_structure(
2676 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
2677 'warnings' => new external_warnings()
2683 * Returns description of method parameters
2685 * @return external_function_parameters
2688 public static function message_processor_config_form_parameters() {
2689 return new external_function_parameters(
2691 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
2692 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
2693 'formvalues' => new external_multiple_structure(
2694 new external_single_structure(
2696 'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
2697 'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
2700 'Config form values',
2708 * Processes a message processor config form.
2710 * @param int $userid the user id
2711 * @param string $name the name of the processor
2712 * @param array $formvalues the form values
2713 * @return external_description
2714 * @throws moodle_exception
2717 public static function message_processor_config_form($userid, $name, $formvalues) {
2720 // Check if messaging is enabled.
2721 if (empty($CFG->messaging)) {
2722 throw new moodle_exception('disabled', 'message');
2725 $params = self::validate_parameters(
2726 self::message_processor_config_form_parameters(),
2728 'userid' => $userid,
2730 'formvalues' => $formvalues,
2734 $user = self::validate_preferences_permissions($params['userid']);
2736 $processor = get_message_processor($name);
2738 $form = new stdClass();
2740 foreach ($formvalues as $formvalue) {
2741 // Curly braces to ensure interpretation is consistent between
2743 $form->{$formvalue['name']} = $formvalue['value'];
2746 $processor->process_form($form, $preferences);
2748 if (!empty($preferences)) {
2749 set_user_preferences($preferences, $userid);
2754 * Returns description of method result value
2756 * @return external_description
2759 public static function message_processor_config_form_returns() {
2764 * Returns description of method parameters
2766 * @return external_function_parameters
2769 public static function get_message_processor_parameters() {
2770 return new external_function_parameters(
2772 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
2773 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
2779 * Get a message processor.
2781 * @param int $userid
2782 * @param string $name the name of the processor
2783 * @return external_description
2784 * @throws moodle_exception
2787 public static function get_message_processor($userid = 0, $name) {
2788 global $USER, $PAGE, $CFG;
2790 // Check if messaging is enabled.
2791 if (empty($CFG->messaging)) {
2792 throw new moodle_exception('disabled', 'message');
2795 $params = self::validate_parameters(
2796 self::get_message_processor_parameters(),
2798 'userid' => $userid,
2803 if (empty($params['userid'])) {
2804 $params['userid'] = $USER->id;
2807 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2808 core_user::require_active_user($user);
2809 self::validate_context(context_user::instance($params['userid']));
2811 $processor = get_message_processor($name);
2813 $processoroutput = new \core_message\output\processor($processor, $user);
2814 $renderer = $PAGE->get_renderer('core_message');
2816 return $processoroutput->export_for_template($renderer);
2820 * Returns description of method result value
2822 * @return external_description
2825 public static function get_message_processor_returns() {
2826 return new external_function_parameters(
2828 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
2829 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
2835 * Check that the user has enough permission to retrieve message or notifications preferences.
2837 * @param int $userid the user id requesting the preferences
2838 * @return stdClass full user object
2839 * @throws moodle_exception
2842 protected static function validate_preferences_permissions($userid) {
2845 if (empty($userid)) {
2848 $user = core_user::get_user($userid, '*', MUST_EXIST);
2849 core_user::require_active_user($user);
2852 $systemcontext = context_system::instance();
2853 self::validate_context($systemcontext);
2855 // Check access control.
2856 if ($user->id == $USER->id) {
2857 // Editing own message profile.
2858 require_capability('moodle/user:editownmessageprofile', $systemcontext);
2860 // Teachers, parents, etc.
2861 $personalcontext = context_user::instance($user->id);
2862 require_capability('moodle/user:editmessageprofile', $personalcontext);
2868 * Returns a notification or message preference structure.
2870 * @return external_single_structure the structure
2873 protected static function get_preferences_structure() {
2874 return new external_single_structure(
2876 'userid' => new external_value(PARAM_INT, 'User id'),
2877 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
2878 'processors' => new external_multiple_structure(
2879 new external_single_structure(
2881 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2882 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2883 'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
2884 'contextid' => new external_value(PARAM_INT, 'Context id'),
2885 'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
2888 'Config form values'
2890 'components' => new external_multiple_structure(
2891 new external_single_structure(
2893 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2894 'notifications' => new external_multiple_structure(
2895 new external_single_structure(
2897 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2898 'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
2899 'processors' => new external_multiple_structure(
2900 new external_single_structure(
2902 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2903 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2904 'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
2905 'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
2906 'loggedin' => new external_single_structure(
2908 'name' => new external_value(PARAM_NOTAGS, 'Name'),
2909 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2910 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2913 'loggedoff' => new external_single_structure(
2915 'name' => new external_value(PARAM_NOTAGS, 'Name'),
2916 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2917 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2922 'Processors values for this notification'
2926 'List of notificaitons for the component'
2930 'Available components'
2937 * Returns description of method parameters
2939 * @return external_function_parameters
2942 public static function get_user_notification_preferences_parameters() {
2943 return new external_function_parameters(
2945 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
2951 * Get the notification preferences for a given user.
2953 * @param int $userid id of the user, 0 for current user
2954 * @return external_description
2955 * @throws moodle_exception
2958 public static function get_user_notification_preferences($userid = 0) {
2961 $params = self::validate_parameters(
2962 self::get_user_notification_preferences_parameters(),
2964 'userid' => $userid,
2967 $user = self::validate_preferences_permissions($params['userid']);
2969 $processors = get_message_processors();
2970 $providers = message_get_providers_for_user($user->id);
2971 $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2972 $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
2974 $renderer = $PAGE->get_renderer('core_message');
2977 'warnings' => array(),
2978 'preferences' => $notificationlist->export_for_template($renderer)
2984 * Returns description of method result value
2986 * @return external_description
2989 public static function get_user_notification_preferences_returns() {
2990 return new external_function_parameters(
2992 'preferences' => self::get_preferences_structure(),
2993 'warnings' => new external_warnings(),
3000 * Returns description of method parameters
3002 * @return external_function_parameters
3005 public static function get_user_message_preferences_parameters() {
3006 return new external_function_parameters(
3008 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
3014 * Get the notification preferences for a given user.
3016 * @param int $userid id of the user, 0 for current user
3017 * @return external_description
3018 * @throws moodle_exception
3021 public static function get_user_message_preferences($userid = 0) {
3024 $params = self::validate_parameters(
3025 self::get_user_message_preferences_parameters(),
3027 'userid' => $userid,
3031 $user = self::validate_preferences_permissions($params['userid']);
3033 // Filter out enabled, available system_configured and user_configured processors only.
3034 $readyprocessors = array_filter(get_message_processors(), function($processor) {
3035 return $processor->enabled &&
3036 $processor->configured &&
3037 $processor->object->is_user_configured() &&
3038 // Filter out processors that don't have and message preferences to configure.
3039 $processor->object->has_message_preferences();
3042 $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
3043 return $provider->component === 'moodle';
3045 $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
3046 $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
3047 $providers, $preferences, $user);
3049 $renderer = $PAGE->get_renderer('core_message');
3052 'warnings' => array(),
3053 'preferences' => $notificationlistoutput->export_for_template($renderer),
3054 'blocknoncontacts' => get_user_preferences('message_blocknoncontacts', '', $user->id) ? true : false,
3060 * Returns description of method result value
3062 * @return external_description
3065 public static function get_user_message_preferences_returns() {
3066 return new external_function_parameters(
3068 'preferences' => self::get_preferences_structure(),
3069 'blocknoncontacts' => new external_value(PARAM_BOOL, 'Whether to block or not messages from non contacts'),
3070 'warnings' => new external_warnings(),