Merge branch 'MDL-63625-master' of git://github.com/marinaglancy/moodle
[moodle.git] / message / externallib.php
blob2936f21603da37b739bc8e7f56b818b555899044
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 {
43 /**
44 * Returns description of method parameters
46 * @return external_function_parameters
47 * @since Moodle 2.2
49 public static function send_instant_messages_parameters() {
50 return new external_function_parameters(
51 array(
52 'messages' => new external_multiple_structure(
53 new external_single_structure(
54 array(
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),
66 /**
67 * Send private messages from the current USER to other users
69 * @param array $messages An array of message to send.
70 * @return array
71 * @since Moodle 2.2
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
89 $receivers = array();
90 foreach($params['messages'] as $message) {
91 $receivers[] = $message['touserid'];
93 list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers);
94 $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
96 $resultmessages = array();
97 foreach ($params['messages'] as $message) {
98 $resultmsg = array(); //the infos about the success of the operation
100 // We are going to do some checking.
101 // Code should match /messages/index.php checks.
102 $success = true;
104 // Check the user exists.
105 if (empty($tousers[$message['touserid']])) {
106 $success = false;
107 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
110 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
111 // Check if the recipient can be messaged by the sender.
112 if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
113 $success = false;
114 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
117 // Now we can send the message (at least try).
118 if ($success) {
119 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
120 $success = message_post_message($USER, $tousers[$message['touserid']],
121 $message['text'], external_validate_format($message['textformat']));
124 // Build the resultmsg.
125 if (isset($message['clientmsgid'])) {
126 $resultmsg['clientmsgid'] = $message['clientmsgid'];
128 if ($success) {
129 $resultmsg['msgid'] = $success;
130 } else {
131 // WARNINGS: for backward compatibility we return this errormessage.
132 // We should have thrown exceptions as these errors prevent results to be returned.
133 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
134 $resultmsg['msgid'] = -1;
135 $resultmsg['errormessage'] = $errormessage;
138 $resultmessages[] = $resultmsg;
141 return $resultmessages;
145 * Returns description of method result value
147 * @return external_description
148 * @since Moodle 2.2
150 public static function send_instant_messages_returns() {
151 return new external_multiple_structure(
152 new external_single_structure(
153 array(
154 'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds: id of the created message if it succeeded, -1 when failed'),
155 'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
156 'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL)
163 * Create contacts parameters description.
165 * @deprecated since Moodle 3.6
166 * @return external_function_parameters
167 * @since Moodle 2.5
169 public static function create_contacts_parameters() {
170 return new external_function_parameters(
171 array(
172 'userids' => new external_multiple_structure(
173 new external_value(PARAM_INT, 'User ID'),
174 'List of user IDs'
176 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
177 current user', VALUE_DEFAULT, 0)
183 * Create contacts.
185 * @deprecated since Moodle 3.6
186 * @param array $userids array of user IDs.
187 * @param int $userid The id of the user we are creating the contacts for
188 * @return external_description
189 * @since Moodle 2.5
191 public static function create_contacts($userids, $userid = 0) {
192 global $CFG, $USER;
194 // Check if messaging is enabled.
195 if (empty($CFG->messaging)) {
196 throw new moodle_exception('disabled', 'message');
199 if (empty($userid)) {
200 $userid = $USER->id;
203 // Validate context.
204 $context = context_system::instance();
205 self::validate_context($context);
207 $capability = 'moodle/site:manageallmessaging';
208 if (($USER->id != $userid) && !has_capability($capability, $context)) {
209 throw new required_capability_exception($context, $capability, 'nopermissions', '');
212 $params = array('userids' => $userids, 'userid' => $userid);
213 $params = self::validate_parameters(self::create_contacts_parameters(), $params);
215 $warnings = array();
216 foreach ($params['userids'] as $id) {
217 if (!message_add_contact($id, 0, $userid)) {
218 $warnings[] = array(
219 'item' => 'user',
220 'itemid' => $id,
221 'warningcode' => 'contactnotcreated',
222 'message' => 'The contact could not be created'
226 return $warnings;
230 * Create contacts return description.
232 * @deprecated since Moodle 3.6
233 * @return external_description
234 * @since Moodle 2.5
236 public static function create_contacts_returns() {
237 return new external_warnings();
241 * Marking the method as deprecated.
243 * @return bool
245 public static function create_contacts_is_deprecated() {
246 return true;
250 * Delete contacts parameters description.
252 * @return external_function_parameters
253 * @since Moodle 2.5
255 public static function delete_contacts_parameters() {
256 return new external_function_parameters(
257 array(
258 'userids' => new external_multiple_structure(
259 new external_value(PARAM_INT, 'User ID'),
260 'List of user IDs'
262 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
263 current user', VALUE_DEFAULT, 0)
269 * Delete contacts.
271 * @param array $userids array of user IDs.
272 * @param int $userid The id of the user we are deleting the contacts for
273 * @return null
274 * @since Moodle 2.5
276 public static function delete_contacts($userids, $userid = 0) {
277 global $CFG, $USER;
279 // Check if messaging is enabled.
280 if (empty($CFG->messaging)) {
281 throw new moodle_exception('disabled', 'message');
284 if (empty($userid)) {
285 $userid = $USER->id;
288 // Validate context.
289 $context = context_system::instance();
290 self::validate_context($context);
292 $capability = 'moodle/site:manageallmessaging';
293 if (($USER->id != $userid) && !has_capability($capability, $context)) {
294 throw new required_capability_exception($context, $capability, 'nopermissions', '');
297 $params = array('userids' => $userids, 'userid' => $userid);
298 $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
300 foreach ($params['userids'] as $id) {
301 \core_message\api::remove_contact($userid, $id);
304 return null;
308 * Delete contacts return description.
310 * @return external_description
311 * @since Moodle 2.5
313 public static function delete_contacts_returns() {
314 return null;
318 * Block user parameters description.
320 * @return external_function_parameters
322 public static function block_user_parameters() {
323 return new external_function_parameters(
325 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
326 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
332 * Blocks a user.
334 * @param int $userid The id of the user who is blocking
335 * @param int $blockeduserid The id of the user being blocked
336 * @return external_description
338 public static function block_user(int $userid, int $blockeduserid) {
339 global $CFG, $USER;
341 // Check if messaging is enabled.
342 if (empty($CFG->messaging)) {
343 throw new moodle_exception('disabled', 'message');
346 // Validate context.
347 $context = context_system::instance();
348 self::validate_context($context);
350 $capability = 'moodle/site:manageallmessaging';
351 if (($USER->id != $userid) && !has_capability($capability, $context)) {
352 throw new required_capability_exception($context, $capability, 'nopermissions', '');
355 $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
356 $params = self::validate_parameters(self::block_user_parameters(), $params);
358 if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
359 \core_message\api::block_user($params['userid'], $params['blockeduserid']);
362 return [];
366 * Block user return description.
368 * @return external_description
370 public static function block_user_returns() {
371 return new external_warnings();
375 * Unblock user parameters description.
377 * @return external_function_parameters
379 public static function unblock_user_parameters() {
380 return new external_function_parameters(
382 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
383 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
389 * Unblock user.
391 * @param int $userid The id of the user who is unblocking
392 * @param int $unblockeduserid The id of the user being unblocked
394 public static function unblock_user(int $userid, int $unblockeduserid) {
395 global $CFG, $USER;
397 // Check if messaging is enabled.
398 if (empty($CFG->messaging)) {
399 throw new moodle_exception('disabled', 'message');
402 // Validate context.
403 $context = context_system::instance();
404 self::validate_context($context);
406 $capability = 'moodle/site:manageallmessaging';
407 if (($USER->id != $userid) && !has_capability($capability, $context)) {
408 throw new required_capability_exception($context, $capability, 'nopermissions', '');
411 $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
412 $params = self::validate_parameters(self::unblock_user_parameters(), $params);
414 \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
416 return [];
420 * Unblock user return description.
422 * @return external_description
424 public static function unblock_user_returns() {
425 return new external_warnings();
429 * Block contacts parameters description.
431 * @deprecated since Moodle 3.6
432 * @return external_function_parameters
433 * @since Moodle 2.5
435 public static function block_contacts_parameters() {
436 return new external_function_parameters(
437 array(
438 'userids' => new external_multiple_structure(
439 new external_value(PARAM_INT, 'User ID'),
440 'List of user IDs'
442 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
443 current user', VALUE_DEFAULT, 0)
449 * Block contacts.
451 * @deprecated since Moodle 3.6
452 * @param array $userids array of user IDs.
453 * @param int $userid The id of the user we are blocking the contacts for
454 * @return external_description
455 * @since Moodle 2.5
457 public static function block_contacts($userids, $userid = 0) {
458 global $CFG, $USER;
460 // Check if messaging is enabled.
461 if (empty($CFG->messaging)) {
462 throw new moodle_exception('disabled', 'message');
465 if (empty($userid)) {
466 $userid = $USER->id;
469 // Validate context.
470 $context = context_system::instance();
471 self::validate_context($context);
473 $capability = 'moodle/site:manageallmessaging';
474 if (($USER->id != $userid) && !has_capability($capability, $context)) {
475 throw new required_capability_exception($context, $capability, 'nopermissions', '');
478 $params = array('userids' => $userids, 'userid' => $userid);
479 $params = self::validate_parameters(self::block_contacts_parameters(), $params);
481 $warnings = array();
482 foreach ($params['userids'] as $id) {
483 if (!message_block_contact($id, $userid)) {
484 $warnings[] = array(
485 'item' => 'user',
486 'itemid' => $id,
487 'warningcode' => 'contactnotblocked',
488 'message' => 'The contact could not be blocked'
492 return $warnings;
496 * Block contacts return description.
498 * @deprecated since Moodle 3.6
499 * @return external_description
500 * @since Moodle 2.5
502 public static function block_contacts_returns() {
503 return new external_warnings();
507 * Marking the method as deprecated.
509 * @return bool
511 public static function block_contacts_is_deprecated() {
512 return true;
516 * Unblock contacts parameters description.
518 * @deprecated since Moodle 3.6
519 * @return external_function_parameters
520 * @since Moodle 2.5
522 public static function unblock_contacts_parameters() {
523 return new external_function_parameters(
524 array(
525 'userids' => new external_multiple_structure(
526 new external_value(PARAM_INT, 'User ID'),
527 'List of user IDs'
529 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
530 current user', VALUE_DEFAULT, 0)
536 * Unblock contacts.
538 * @param array $userids array of user IDs.
539 * @param int $userid The id of the user we are unblocking the contacts for
540 * @return null
541 * @since Moodle 2.5
543 public static function unblock_contacts($userids, $userid = 0) {
544 global $CFG, $USER;
546 // Check if messaging is enabled.
547 if (empty($CFG->messaging)) {
548 throw new moodle_exception('disabled', 'message');
551 if (empty($userid)) {
552 $userid = $USER->id;
555 // Validate context.
556 $context = context_system::instance();
557 self::validate_context($context);
559 $capability = 'moodle/site:manageallmessaging';
560 if (($USER->id != $userid) && !has_capability($capability, $context)) {
561 throw new required_capability_exception($context, $capability, 'nopermissions', '');
564 $params = array('userids' => $userids, 'userid' => $userid);
565 $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
567 foreach ($params['userids'] as $id) {
568 message_unblock_contact($id, $userid);
571 return null;
575 * Unblock contacts return description.
577 * @deprecated since Moodle 3.6
578 * @return external_description
579 * @since Moodle 2.5
581 public static function unblock_contacts_returns() {
582 return null;
586 * Marking the method as deprecated.
588 * @return bool
590 public static function unblock_contacts_is_deprecated() {
591 return true;
595 * Returns contact requests parameters description.
597 * @return external_function_parameters
599 public static function get_contact_requests_parameters() {
600 return new external_function_parameters(
602 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for')
608 * Handles returning the contact requests for a user.
610 * This also includes the user data necessary to display information
611 * about the user.
613 * It will not include blocked users.
615 * @param int $userid The id of the user we want to get the contact requests for
617 public static function get_contact_requests(int $userid) {
618 global $CFG, $USER;
620 // Check if messaging is enabled.
621 if (empty($CFG->messaging)) {
622 throw new moodle_exception('disabled', 'message');
625 // Validate context.
626 $context = context_system::instance();
627 self::validate_context($context);
629 $capability = 'moodle/site:manageallmessaging';
630 if (($USER->id != $userid) && !has_capability($capability, $context)) {
631 throw new required_capability_exception($context, $capability, 'nopermissions', '');
634 $params = ['userid' => $userid];
635 $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
637 return \core_message\api::get_contact_requests($params['userid']);
641 * Returns the contact requests return description.
643 * @return external_description
645 public static function get_contact_requests_returns() {
646 return new external_multiple_structure(
647 new external_single_structure(
649 'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'),
650 'contactrequestid' => new external_value(PARAM_INT, 'The ID of the contact request'),
651 'picture' => new external_value(core_user::get_property_type('picture'), 'The picture'),
652 'firstname' => new external_value(core_user::get_property_type('firstname'),
653 'The first name(s) of the user'),
654 'lastname' => new external_value(core_user::get_property_type('lastname'),
655 'The family name of the user'),
656 'firstnamephonetic' => new external_value(core_user::get_property_type('firstnamephonetic'),
657 'The phonetic first name of the user'),
658 'lastnamephonetic' => new external_value(core_user::get_property_type('lastnamephonetic'),
659 'The phonetic last name of the user'),
660 'middlename' => new external_value(core_user::get_property_type('middlename'),
661 'The middle name of the user'),
662 'alternatename' => new external_value(core_user::get_property_type('alternatename'),
663 'The alternate name of the user'),
664 'email' => new external_value(core_user::get_property_type('email'), 'An email address')
671 * Creates a contact request parameters description.
673 * @return external_function_parameters
675 public static function create_contact_request_parameters() {
676 return new external_function_parameters(
678 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
679 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
685 * Creates a contact request.
687 * @param int $userid The id of the user who is creating the contact request
688 * @param int $requesteduserid The id of the user being requested
690 public static function create_contact_request(int $userid, int $requesteduserid) {
691 global $CFG, $USER;
693 // Check if messaging is enabled.
694 if (empty($CFG->messaging)) {
695 throw new moodle_exception('disabled', 'message');
698 // Validate context.
699 $context = context_system::instance();
700 self::validate_context($context);
702 $capability = 'moodle/site:manageallmessaging';
703 if (($USER->id != $userid) && !has_capability($capability, $context)) {
704 throw new required_capability_exception($context, $capability, 'nopermissions', '');
707 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
708 $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
710 if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
711 $warning[] = [
712 'item' => 'user',
713 'itemid' => $params['requesteduserid'],
714 'warningcode' => 'cannotcreatecontactrequest',
715 'message' => 'You are unable to create a contact request for this user'
717 return $warning;
720 if (!\core_message\api::does_contact_request_exist($params['userid'], $params['requesteduserid'])) {
721 \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
724 return [];
728 * Creates a contact request return description.
730 * @return external_description
732 public static function create_contact_request_returns() {
733 return new external_warnings();
737 * Confirm a contact request parameters description.
739 * @return external_function_parameters
741 public static function confirm_contact_request_parameters() {
742 return new external_function_parameters(
744 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
745 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
751 * Confirm a contact request.
753 * @param int $userid The id of the user who is creating the contact request
754 * @param int $requesteduserid The id of the user being requested
756 public static function confirm_contact_request(int $userid, int $requesteduserid) {
757 global $CFG, $USER;
759 // Check if messaging is enabled.
760 if (empty($CFG->messaging)) {
761 throw new moodle_exception('disabled', 'message');
764 // Validate context.
765 $context = context_system::instance();
766 self::validate_context($context);
768 $capability = 'moodle/site:manageallmessaging';
769 if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
770 throw new required_capability_exception($context, $capability, 'nopermissions', '');
773 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
774 $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
776 \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
778 return [];
782 * Confirm a contact request return description.
784 * @return external_description
786 public static function confirm_contact_request_returns() {
787 return new external_warnings();
791 * Declines a contact request parameters description.
793 * @return external_function_parameters
795 public static function decline_contact_request_parameters() {
796 return new external_function_parameters(
798 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
799 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
805 * Declines a contact request.
807 * @param int $userid The id of the user who is creating the contact request
808 * @param int $requesteduserid The id of the user being requested
810 public static function decline_contact_request(int $userid, int $requesteduserid) {
811 global $CFG, $USER;
813 // Check if messaging is enabled.
814 if (empty($CFG->messaging)) {
815 throw new moodle_exception('disabled', 'message');
818 // Validate context.
819 $context = context_system::instance();
820 self::validate_context($context);
822 $capability = 'moodle/site:manageallmessaging';
823 if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
824 throw new required_capability_exception($context, $capability, 'nopermissions', '');
827 $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
828 $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
830 \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
832 return [];
836 * Declines a contact request return description.
838 * @return external_description
840 public static function decline_contact_request_returns() {
841 return new external_warnings();
845 * Return the structure of a message area contact.
847 * @return external_single_structure
848 * @since Moodle 3.2
850 private static function get_messagearea_contact_structure() {
851 return new external_single_structure(
852 array(
853 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
854 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
855 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
856 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
857 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
858 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
859 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
860 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
861 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
862 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
863 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
864 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
865 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
866 VALUE_DEFAULT, null),
872 * Return the structure of a message area message.
874 * @return external_single_structure
875 * @since Moodle 3.2
877 private static function get_messagearea_message_structure() {
878 return new external_single_structure(
879 array(
880 'id' => new external_value(PARAM_INT, 'The id of the message'),
881 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
882 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
883 'text' => new external_value(PARAM_RAW, 'The text of the message'),
884 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
885 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
886 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
887 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
888 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
889 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
895 * Get messagearea search users in course parameters.
897 * @return external_function_parameters
898 * @since 3.2
900 public static function data_for_messagearea_search_users_in_course_parameters() {
901 return new external_function_parameters(
902 array(
903 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
904 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
905 'search' => new external_value(PARAM_RAW, 'The string being searched'),
906 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
907 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
913 * Get messagearea search users in course results.
915 * @param int $userid The id of the user who is performing the search
916 * @param int $courseid The id of the course
917 * @param string $search The string being searched
918 * @param int $limitfrom
919 * @param int $limitnum
920 * @return stdClass
921 * @throws moodle_exception
922 * @since 3.2
924 public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
925 $limitnum = 0) {
926 global $CFG, $PAGE, $USER;
928 // Check if messaging is enabled.
929 if (empty($CFG->messaging)) {
930 throw new moodle_exception('disabled', 'message');
933 $systemcontext = context_system::instance();
935 $params = array(
936 'userid' => $userid,
937 'courseid' => $courseid,
938 'search' => $search,
939 'limitfrom' => $limitfrom,
940 'limitnum' => $limitnum
942 self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
943 self::validate_context($systemcontext);
945 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
946 throw new moodle_exception('You do not have permission to perform this action.');
949 $users = \core_message\api::search_users_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
950 $results = new \core_message\output\messagearea\user_search_results($users);
952 $renderer = $PAGE->get_renderer('core_message');
953 return $results->export_for_template($renderer);
957 * Get messagearea search users in course returns.
959 * @return external_single_structure
960 * @since 3.2
962 public static function data_for_messagearea_search_users_in_course_returns() {
963 return new external_single_structure(
964 array(
965 'contacts' => new external_multiple_structure(
966 self::get_messagearea_contact_structure()
973 * Get messagearea search users parameters.
975 * @return external_function_parameters
976 * @since 3.2
978 public static function data_for_messagearea_search_users_parameters() {
979 return new external_function_parameters(
980 array(
981 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
982 'search' => new external_value(PARAM_RAW, 'The string being searched'),
983 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
989 * Get messagearea search users results.
991 * @param int $userid The id of the user who is performing the search
992 * @param string $search The string being searched
993 * @param int $limitnum
994 * @return stdClass
995 * @throws moodle_exception
996 * @since 3.2
998 public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
999 global $CFG, $PAGE, $USER;
1001 // Check if messaging is enabled.
1002 if (empty($CFG->messaging)) {
1003 throw new moodle_exception('disabled', 'message');
1006 $systemcontext = context_system::instance();
1008 $params = array(
1009 'userid' => $userid,
1010 'search' => $search,
1011 'limitnum' => $limitnum
1013 self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1014 self::validate_context($systemcontext);
1016 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1017 throw new moodle_exception('You do not have permission to perform this action.');
1020 list($contacts, $courses, $noncontacts) = \core_message\api::search_users($userid, $search, $limitnum);
1021 $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1023 $renderer = $PAGE->get_renderer('core_message');
1024 return $search->export_for_template($renderer);
1028 * Get messagearea search users returns.
1030 * @return external_single_structure
1031 * @since 3.2
1033 public static function data_for_messagearea_search_users_returns() {
1034 return new external_single_structure(
1035 array(
1036 'contacts' => new external_multiple_structure(
1037 self::get_messagearea_contact_structure()
1039 'courses' => new external_multiple_structure(
1040 new external_single_structure(
1041 array(
1042 'id' => new external_value(PARAM_INT, 'The course id'),
1043 'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1044 'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1048 'noncontacts' => new external_multiple_structure(
1049 self::get_messagearea_contact_structure()
1056 * Get messagearea search messages parameters.
1058 * @return external_function_parameters
1059 * @since 3.2
1061 public static function data_for_messagearea_search_messages_parameters() {
1062 return new external_function_parameters(
1063 array(
1064 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1065 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1066 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1067 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1073 * Get messagearea search messages results.
1075 * @param int $userid The id of the user who is performing the search
1076 * @param string $search The string being searched
1077 * @param int $limitfrom
1078 * @param int $limitnum
1079 * @return stdClass
1080 * @throws moodle_exception
1081 * @since 3.2
1083 public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1084 global $CFG, $PAGE, $USER;
1086 // Check if messaging is enabled.
1087 if (empty($CFG->messaging)) {
1088 throw new moodle_exception('disabled', 'message');
1091 $systemcontext = context_system::instance();
1093 $params = array(
1094 'userid' => $userid,
1095 'search' => $search,
1096 'limitfrom' => $limitfrom,
1097 'limitnum' => $limitnum
1100 self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1101 self::validate_context($systemcontext);
1103 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1104 throw new moodle_exception('You do not have permission to perform this action.');
1107 $messages = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
1108 $results = new \core_message\output\messagearea\message_search_results($messages);
1110 $renderer = $PAGE->get_renderer('core_message');
1111 return $results->export_for_template($renderer);
1115 * Get messagearea search messages returns.
1117 * @return external_single_structure
1118 * @since 3.2
1120 public static function data_for_messagearea_search_messages_returns() {
1121 return new external_single_structure(
1122 array(
1123 'contacts' => new external_multiple_structure(
1124 self::get_messagearea_contact_structure()
1131 * The messagearea conversations parameters.
1133 * @return external_function_parameters
1134 * @since 3.2
1136 public static function data_for_messagearea_conversations_parameters() {
1137 return new external_function_parameters(
1138 array(
1139 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1140 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1141 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1147 * Get messagearea conversations.
1149 * @param int $userid The id of the user who we are viewing conversations for
1150 * @param int $limitfrom
1151 * @param int $limitnum
1152 * @return stdClass
1153 * @throws moodle_exception
1154 * @since 3.2
1156 public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1157 global $CFG, $PAGE, $USER;
1159 // Check if messaging is enabled.
1160 if (empty($CFG->messaging)) {
1161 throw new moodle_exception('disabled', 'message');
1164 $systemcontext = context_system::instance();
1166 $params = array(
1167 'userid' => $userid,
1168 'limitfrom' => $limitfrom,
1169 'limitnum' => $limitnum
1171 self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1172 self::validate_context($systemcontext);
1174 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1175 throw new moodle_exception('You do not have permission to perform this action.');
1178 $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum);
1179 $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1181 $renderer = $PAGE->get_renderer('core_message');
1182 return $conversations->export_for_template($renderer);
1186 * The messagearea conversations return structure.
1188 * @return external_single_structure
1189 * @since 3.2
1191 public static function data_for_messagearea_conversations_returns() {
1192 return new external_single_structure(
1193 array(
1194 'contacts' => new external_multiple_structure(
1195 self::get_messagearea_contact_structure()
1202 * The messagearea contacts return parameters.
1204 * @return external_function_parameters
1205 * @since 3.2
1207 public static function data_for_messagearea_contacts_parameters() {
1208 return self::data_for_messagearea_conversations_parameters();
1212 * Get messagearea contacts parameters.
1214 * @param int $userid The id of the user who we are viewing conversations for
1215 * @param int $limitfrom
1216 * @param int $limitnum
1217 * @return stdClass
1218 * @throws moodle_exception
1219 * @since 3.2
1221 public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1222 global $CFG, $PAGE, $USER;
1224 // Check if messaging is enabled.
1225 if (empty($CFG->messaging)) {
1226 throw new moodle_exception('disabled', 'message');
1229 $systemcontext = context_system::instance();
1231 $params = array(
1232 'userid' => $userid,
1233 'limitfrom' => $limitfrom,
1234 'limitnum' => $limitnum
1236 self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1237 self::validate_context($systemcontext);
1239 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1240 throw new moodle_exception('You do not have permission to perform this action.');
1243 $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
1244 $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1246 $renderer = $PAGE->get_renderer('core_message');
1247 return $contacts->export_for_template($renderer);
1251 * The messagearea contacts return structure.
1253 * @return external_single_structure
1254 * @since 3.2
1256 public static function data_for_messagearea_contacts_returns() {
1257 return self::data_for_messagearea_conversations_returns();
1261 * The messagearea messages parameters.
1263 * @return external_function_parameters
1264 * @since 3.2
1266 public static function data_for_messagearea_messages_parameters() {
1267 return new external_function_parameters(
1268 array(
1269 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1270 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1271 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1272 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1273 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1274 'timefrom' => new external_value(PARAM_INT,
1275 'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1281 * Get messagearea messages.
1283 * @param int $currentuserid The current user's id
1284 * @param int $otheruserid The other user's id
1285 * @param int $limitfrom
1286 * @param int $limitnum
1287 * @param boolean $newest
1288 * @return stdClass
1289 * @throws moodle_exception
1290 * @since 3.2
1292 public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
1293 $newest = false, $timefrom = 0) {
1294 global $CFG, $PAGE, $USER;
1296 // Check if messaging is enabled.
1297 if (empty($CFG->messaging)) {
1298 throw new moodle_exception('disabled', 'message');
1301 $systemcontext = context_system::instance();
1303 $params = array(
1304 'currentuserid' => $currentuserid,
1305 'otheruserid' => $otheruserid,
1306 'limitfrom' => $limitfrom,
1307 'limitnum' => $limitnum,
1308 'newest' => $newest,
1309 'timefrom' => $timefrom,
1311 self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
1312 self::validate_context($systemcontext);
1314 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1315 throw new moodle_exception('You do not have permission to perform this action.');
1318 if ($newest) {
1319 $sort = 'timecreated DESC';
1320 } else {
1321 $sort = 'timecreated ASC';
1324 // We need to enforce a one second delay on messages to avoid race conditions of current
1325 // messages still being sent.
1327 // There is a chance that we could request messages before the current time's
1328 // second has elapsed and while other messages are being sent in that same second. In which
1329 // case those messages will be lost.
1331 // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1332 if (!empty($timefrom)) {
1333 $timeto = time() - 1;
1334 } else {
1335 $timeto = 0;
1338 // No requesting messages from the current time, as stated above.
1339 if ($timefrom == time()) {
1340 $messages = [];
1341 } else {
1342 $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
1343 $limitnum, $sort, $timefrom, $timeto);
1346 $messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
1348 $renderer = $PAGE->get_renderer('core_message');
1349 return $messages->export_for_template($renderer);
1353 * The messagearea messages return structure.
1355 * @return external_single_structure
1356 * @since 3.2
1358 public static function data_for_messagearea_messages_returns() {
1359 return new external_single_structure(
1360 array(
1361 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
1362 the messages on behalf of?'),
1363 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1364 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1365 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
1366 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1367 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1368 'messages' => new external_multiple_structure(
1369 self::get_messagearea_message_structure()
1371 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
1377 * The get most recent message return parameters.
1379 * @return external_function_parameters
1380 * @since 3.2
1382 public static function data_for_messagearea_get_most_recent_message_parameters() {
1383 return new external_function_parameters(
1384 array(
1385 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1386 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1392 * Get the most recent message in a conversation.
1394 * @param int $currentuserid The current user's id
1395 * @param int $otheruserid The other user's id
1396 * @return stdClass
1397 * @throws moodle_exception
1398 * @since 3.2
1400 public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
1401 global $CFG, $PAGE, $USER;
1403 // Check if messaging is enabled.
1404 if (empty($CFG->messaging)) {
1405 throw new moodle_exception('disabled', 'message');
1408 $systemcontext = context_system::instance();
1410 $params = array(
1411 'currentuserid' => $currentuserid,
1412 'otheruserid' => $otheruserid
1414 self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
1415 self::validate_context($systemcontext);
1417 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1418 throw new moodle_exception('You do not have permission to perform this action.');
1421 $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
1422 $message = new \core_message\output\messagearea\message($message);
1424 $renderer = $PAGE->get_renderer('core_message');
1425 return $message->export_for_template($renderer);
1429 * The get most recent message return structure.
1431 * @return external_single_structure
1432 * @since 3.2
1434 public static function data_for_messagearea_get_most_recent_message_returns() {
1435 return self::get_messagearea_message_structure();
1439 * The get profile parameters.
1441 * @return external_function_parameters
1442 * @since 3.2
1444 public static function data_for_messagearea_get_profile_parameters() {
1445 return new external_function_parameters(
1446 array(
1447 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1448 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
1454 * Get the profile information for a contact.
1456 * @param int $currentuserid The current user's id
1457 * @param int $otheruserid The id of the user whose profile we are viewing
1458 * @return stdClass
1459 * @throws moodle_exception
1460 * @since 3.2
1462 public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
1463 global $CFG, $PAGE, $USER;
1465 // Check if messaging is enabled.
1466 if (empty($CFG->messaging)) {
1467 throw new moodle_exception('disabled', 'message');
1470 $systemcontext = context_system::instance();
1472 $params = array(
1473 'currentuserid' => $currentuserid,
1474 'otheruserid' => $otheruserid
1476 self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
1477 self::validate_context($systemcontext);
1479 if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1480 throw new moodle_exception('You do not have permission to perform this action.');
1483 $profile = \core_message\api::get_profile($currentuserid, $otheruserid);
1484 $profile = new \core_message\output\messagearea\profile($profile);
1486 $renderer = $PAGE->get_renderer('core_message');
1487 return $profile->export_for_template($renderer);
1491 * The get profile return structure.
1493 * @return external_single_structure
1494 * @since 3.2
1496 public static function data_for_messagearea_get_profile_returns() {
1497 return new external_single_structure(
1498 array(
1499 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
1500 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
1501 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
1502 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
1503 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1504 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1505 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1506 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1507 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1508 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
1509 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
1515 * Get contacts parameters description.
1517 * @return external_function_parameters
1518 * @since Moodle 2.5
1520 public static function get_contacts_parameters() {
1521 return new external_function_parameters(array());
1525 * Get contacts.
1527 * @return external_description
1528 * @since Moodle 2.5
1530 public static function get_contacts() {
1531 global $CFG, $PAGE, $USER;
1533 // Check if messaging is enabled.
1534 if (empty($CFG->messaging)) {
1535 throw new moodle_exception('disabled', 'message');
1538 require_once($CFG->dirroot . '/user/lib.php');
1540 $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
1541 $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
1542 foreach ($contacts as $contact) {
1543 // Set the mode.
1544 $mode = 'offline';
1545 if (\core_message\helper::is_online($contact->lastaccess)) {
1546 $mode = 'online';
1549 $newcontact = array(
1550 'id' => $contact->id,
1551 'fullname' => fullname($contact),
1552 'unread' => $contact->messagecount
1555 $userpicture = new user_picture($contact);
1556 $userpicture->size = 1; // Size f1.
1557 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1558 $userpicture->size = 0; // Size f2.
1559 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1561 $allcontacts[$mode][$contact->id] = $newcontact;
1564 $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
1565 foreach ($strangers as $contact) {
1566 $newcontact = array(
1567 'id' => $contact->id,
1568 'fullname' => fullname($contact),
1569 'unread' => $contact->messagecount
1572 $userpicture = new user_picture($contact);
1573 $userpicture->size = 1; // Size f1.
1574 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1575 $userpicture->size = 0; // Size f2.
1576 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1578 $allcontacts['strangers'][$contact->id] = $newcontact;
1581 // Add noreply user and support user to the list, if they don't exist.
1582 $supportuser = core_user::get_support_user();
1583 if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
1584 $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
1585 if ($supportuser->messagecount > 0) {
1586 $supportuser->fullname = fullname($supportuser);
1587 $supportuser->unread = $supportuser->messagecount;
1588 $allcontacts['strangers'][$supportuser->id] = $supportuser;
1592 $noreplyuser = core_user::get_noreply_user();
1593 if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
1594 $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
1595 if ($noreplyuser->messagecount > 0) {
1596 $noreplyuser->fullname = fullname($noreplyuser);
1597 $noreplyuser->unread = $noreplyuser->messagecount;
1598 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
1602 return $allcontacts;
1606 * Get contacts return description.
1608 * @return external_description
1609 * @since Moodle 2.5
1611 public static function get_contacts_returns() {
1612 return new external_single_structure(
1613 array(
1614 'online' => new external_multiple_structure(
1615 new external_single_structure(
1616 array(
1617 'id' => new external_value(PARAM_INT, 'User ID'),
1618 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1619 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1620 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1621 'unread' => new external_value(PARAM_INT, 'Unread message count')
1624 'List of online contacts'
1626 'offline' => new external_multiple_structure(
1627 new external_single_structure(
1628 array(
1629 'id' => new external_value(PARAM_INT, 'User ID'),
1630 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1631 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1632 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1633 'unread' => new external_value(PARAM_INT, 'Unread message count')
1636 'List of offline contacts'
1638 'strangers' => new external_multiple_structure(
1639 new external_single_structure(
1640 array(
1641 'id' => new external_value(PARAM_INT, 'User ID'),
1642 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1643 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1644 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1645 'unread' => new external_value(PARAM_INT, 'Unread message count')
1648 'List of users that are not in the user\'s contact list but have sent a message'
1655 * Search contacts parameters description.
1657 * @return external_function_parameters
1658 * @since Moodle 2.5
1660 public static function search_contacts_parameters() {
1661 return new external_function_parameters(
1662 array(
1663 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
1664 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
1665 VALUE_DEFAULT, false)
1671 * Search contacts.
1673 * @param string $searchtext query string.
1674 * @param bool $onlymycourses limit the search to the user's courses only.
1675 * @return external_description
1676 * @since Moodle 2.5
1678 public static function search_contacts($searchtext, $onlymycourses = false) {
1679 global $CFG, $USER, $PAGE;
1680 require_once($CFG->dirroot . '/user/lib.php');
1682 // Check if messaging is enabled.
1683 if (empty($CFG->messaging)) {
1684 throw new moodle_exception('disabled', 'message');
1687 require_once($CFG->libdir . '/enrollib.php');
1689 $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
1690 $params = self::validate_parameters(self::search_contacts_parameters(), $params);
1692 // Extra validation, we do not allow empty queries.
1693 if ($params['searchtext'] === '') {
1694 throw new moodle_exception('querystringcannotbeempty');
1697 $courseids = array();
1698 if ($params['onlymycourses']) {
1699 $mycourses = enrol_get_my_courses(array('id'));
1700 foreach ($mycourses as $mycourse) {
1701 $courseids[] = $mycourse->id;
1703 } else {
1704 $courseids[] = SITEID;
1707 // Retrieving the users matching the query.
1708 $users = message_search_users($courseids, $params['searchtext']);
1709 $results = array();
1710 foreach ($users as $user) {
1711 $results[$user->id] = $user;
1714 // Reorganising information.
1715 foreach ($results as &$user) {
1716 $newuser = array(
1717 'id' => $user->id,
1718 'fullname' => fullname($user)
1721 // Avoid undefined property notice as phone not specified.
1722 $user->phone1 = null;
1723 $user->phone2 = null;
1725 $userpicture = new user_picture($user);
1726 $userpicture->size = 1; // Size f1.
1727 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1728 $userpicture->size = 0; // Size f2.
1729 $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1731 $user = $newuser;
1734 return $results;
1738 * Search contacts return description.
1740 * @return external_description
1741 * @since Moodle 2.5
1743 public static function search_contacts_returns() {
1744 return new external_multiple_structure(
1745 new external_single_structure(
1746 array(
1747 'id' => new external_value(PARAM_INT, 'User ID'),
1748 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1749 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1750 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
1753 'List of contacts'
1758 * Get messages parameters description.
1760 * @return external_function_parameters
1761 * @since 2.8
1763 public static function get_messages_parameters() {
1764 return new external_function_parameters(
1765 array(
1766 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1767 'useridfrom' => new external_value(
1768 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1769 VALUE_DEFAULT, 0),
1770 'type' => new external_value(
1771 PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
1772 VALUE_DEFAULT, 'both'),
1773 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
1774 'newestfirst' => new external_value(
1775 PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
1776 VALUE_DEFAULT, true),
1777 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
1778 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
1784 * Get messages function implementation.
1786 * @since 2.8
1787 * @throws invalid_parameter_exception
1788 * @throws moodle_exception
1789 * @param int $useridto the user id who received the message
1790 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
1791 * @param string $type type of message to return, expected values: notifications, conversations and both
1792 * @param bool $read true for retreiving read messages, false for unread
1793 * @param bool $newestfirst true for ordering by newest first, false for oldest first
1794 * @param int $limitfrom limit from
1795 * @param int $limitnum limit num
1796 * @return external_description
1798 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
1799 $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
1800 global $CFG, $USER;
1802 $warnings = array();
1804 $params = array(
1805 'useridto' => $useridto,
1806 'useridfrom' => $useridfrom,
1807 'type' => $type,
1808 'read' => $read,
1809 'newestfirst' => $newestfirst,
1810 'limitfrom' => $limitfrom,
1811 'limitnum' => $limitnum
1814 $params = self::validate_parameters(self::get_messages_parameters(), $params);
1816 $context = context_system::instance();
1817 self::validate_context($context);
1819 $useridto = $params['useridto'];
1820 $useridfrom = $params['useridfrom'];
1821 $type = $params['type'];
1822 $read = $params['read'];
1823 $newestfirst = $params['newestfirst'];
1824 $limitfrom = $params['limitfrom'];
1825 $limitnum = $params['limitnum'];
1827 $allowedvalues = array('notifications', 'conversations', 'both');
1828 if (!in_array($type, $allowedvalues)) {
1829 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
1830 'allowed values are: ' . implode(',', $allowedvalues));
1833 // Check if private messaging between users is allowed.
1834 if (empty($CFG->messaging)) {
1835 // If we are retreiving only conversations, and messaging is disabled, throw an exception.
1836 if ($type == "conversations") {
1837 throw new moodle_exception('disabled', 'message');
1839 if ($type == "both") {
1840 $warning = array();
1841 $warning['item'] = 'message';
1842 $warning['itemid'] = $USER->id;
1843 $warning['warningcode'] = '1';
1844 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
1845 Only notifications will be returned';
1846 $warnings[] = $warning;
1850 if (!empty($useridto)) {
1851 if (core_user::is_real_user($useridto)) {
1852 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1853 } else {
1854 throw new moodle_exception('invaliduser');
1858 if (!empty($useridfrom)) {
1859 // We use get_user here because the from user can be the noreply or support user.
1860 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1863 // Check if the current user is the sender/receiver or just a privileged user.
1864 if ($useridto != $USER->id and $useridfrom != $USER->id and
1865 !has_capability('moodle/site:readallmessages', $context)) {
1866 throw new moodle_exception('accessdenied', 'admin');
1869 // Which type of messages to retrieve.
1870 $notifications = -1;
1871 if ($type != 'both') {
1872 $notifications = ($type == 'notifications') ? 1 : 0;
1875 $orderdirection = $newestfirst ? 'DESC' : 'ASC';
1876 $sort = "mr.timecreated $orderdirection";
1878 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
1879 $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
1881 // In some cases, we don't need to get the to/from user objects from the sql query.
1882 $userfromfullname = '';
1883 $usertofullname = '';
1885 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
1886 if (!empty($useridto)) {
1887 $usertofullname = fullname($userto, $canviewfullname);
1888 // The user from may or may not be filled.
1889 if (!empty($useridfrom)) {
1890 $userfromfullname = fullname($userfrom, $canviewfullname);
1892 } else {
1893 // If the useridto field is empty, the useridfrom must be filled.
1894 $userfromfullname = fullname($userfrom, $canviewfullname);
1896 foreach ($messages as $mid => $message) {
1898 // Do not return deleted messages.
1899 if (!$message->notification) {
1900 if (($useridto == $USER->id and $message->timeusertodeleted) or
1901 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
1902 unset($messages[$mid]);
1903 continue;
1907 // We need to get the user from the query.
1908 if (empty($userfromfullname)) {
1909 // Check for non-reply and support users.
1910 if (core_user::is_real_user($message->useridfrom)) {
1911 $user = new stdClass();
1912 $user = username_load_fields_from_object($user, $message, 'userfrom');
1913 $message->userfromfullname = fullname($user, $canviewfullname);
1914 } else {
1915 $user = core_user::get_user($message->useridfrom);
1916 $message->userfromfullname = fullname($user, $canviewfullname);
1918 } else {
1919 $message->userfromfullname = $userfromfullname;
1922 // We need to get the user from the query.
1923 if (empty($usertofullname)) {
1924 $user = new stdClass();
1925 $user = username_load_fields_from_object($user, $message, 'userto');
1926 $message->usertofullname = fullname($user, $canviewfullname);
1927 } else {
1928 $message->usertofullname = $usertofullname;
1931 $message->text = message_format_message_text($message);
1932 $messages[$mid] = (array) $message;
1936 $results = array(
1937 'messages' => $messages,
1938 'warnings' => $warnings
1941 return $results;
1945 * Get messages return description.
1947 * @return external_single_structure
1948 * @since 2.8
1950 public static function get_messages_returns() {
1951 return new external_single_structure(
1952 array(
1953 'messages' => new external_multiple_structure(
1954 new external_single_structure(
1955 array(
1956 'id' => new external_value(PARAM_INT, 'Message id'),
1957 'useridfrom' => new external_value(PARAM_INT, 'User from id'),
1958 'useridto' => new external_value(PARAM_INT, 'User to id'),
1959 'subject' => new external_value(PARAM_TEXT, 'The message subject'),
1960 'text' => new external_value(PARAM_RAW, 'The message text formated'),
1961 'fullmessage' => new external_value(PARAM_RAW, 'The message'),
1962 'fullmessageformat' => new external_format_value('fullmessage'),
1963 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
1964 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
1965 'notification' => new external_value(PARAM_INT, 'Is a notification?'),
1966 'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
1967 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
1968 'timecreated' => new external_value(PARAM_INT, 'Time created'),
1969 'timeread' => new external_value(PARAM_INT, 'Time read'),
1970 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
1971 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
1972 ), 'message'
1975 'warnings' => new external_warnings()
1981 * Mark all notifications as read parameters description.
1983 * @return external_function_parameters
1984 * @since 3.2
1986 public static function mark_all_notifications_as_read_parameters() {
1987 return new external_function_parameters(
1988 array(
1989 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1990 'useridfrom' => new external_value(
1991 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1992 VALUE_DEFAULT, 0),
1998 * Mark all notifications as read function.
2000 * @since 3.2
2001 * @throws invalid_parameter_exception
2002 * @throws moodle_exception
2003 * @param int $useridto the user id who received the message
2004 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2005 * @return external_description
2007 public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2008 global $USER;
2010 $params = self::validate_parameters(
2011 self::mark_all_notifications_as_read_parameters(),
2012 array(
2013 'useridto' => $useridto,
2014 'useridfrom' => $useridfrom,
2018 $context = context_system::instance();
2019 self::validate_context($context);
2021 $useridto = $params['useridto'];
2022 $useridfrom = $params['useridfrom'];
2024 if (!empty($useridto)) {
2025 if (core_user::is_real_user($useridto)) {
2026 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2027 } else {
2028 throw new moodle_exception('invaliduser');
2032 if (!empty($useridfrom)) {
2033 // We use get_user here because the from user can be the noreply or support user.
2034 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2037 // Check if the current user is the sender/receiver or just a privileged user.
2038 if ($useridto != $USER->id and $useridfrom != $USER->id and
2039 // The deleteanymessage cap seems more reasonable here than readallmessages.
2040 !has_capability('moodle/site:deleteanymessage', $context)) {
2041 throw new moodle_exception('accessdenied', 'admin');
2044 \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2046 return true;
2050 * Mark all notifications as read return description.
2052 * @return external_single_structure
2053 * @since 3.2
2055 public static function mark_all_notifications_as_read_returns() {
2056 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2060 * Get unread conversations count parameters description.
2062 * @return external_function_parameters
2063 * @since 3.2
2065 public static function get_unread_conversations_count_parameters() {
2066 return new external_function_parameters(
2067 array(
2068 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2074 * Get unread messages count function.
2076 * @since 3.2
2077 * @throws invalid_parameter_exception
2078 * @throws moodle_exception
2079 * @param int $useridto the user id who received the message
2080 * @return external_description
2082 public static function get_unread_conversations_count($useridto) {
2083 global $USER, $CFG;
2085 // Check if messaging is enabled.
2086 if (empty($CFG->messaging)) {
2087 throw new moodle_exception('disabled', 'message');
2090 $params = self::validate_parameters(
2091 self::get_unread_conversations_count_parameters(),
2092 array('useridto' => $useridto)
2095 $context = context_system::instance();
2096 self::validate_context($context);
2098 $useridto = $params['useridto'];
2100 if (!empty($useridto)) {
2101 if (core_user::is_real_user($useridto)) {
2102 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2103 } else {
2104 throw new moodle_exception('invaliduser');
2106 } else {
2107 $useridto = $USER->id;
2110 // Check if the current user is the receiver or just a privileged user.
2111 if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2112 throw new moodle_exception('accessdenied', 'admin');
2115 return \core_message\api::count_unread_conversations($userto);
2119 * Get unread conversations count return description.
2121 * @return external_single_structure
2122 * @since 3.2
2124 public static function get_unread_conversations_count_returns() {
2125 return new external_value(PARAM_INT, 'The count of unread messages for the user');
2129 * Get blocked users parameters description.
2131 * @return external_function_parameters
2132 * @since 2.9
2134 public static function get_blocked_users_parameters() {
2135 return new external_function_parameters(
2136 array(
2137 'userid' => new external_value(PARAM_INT,
2138 'the user whose blocked users we want to retrieve',
2139 VALUE_REQUIRED),
2145 * Retrieve a list of users blocked
2147 * @param int $userid the user whose blocked users we want to retrieve
2148 * @return external_description
2149 * @since 2.9
2151 public static function get_blocked_users($userid) {
2152 global $CFG, $USER, $PAGE;
2154 // Warnings array, it can be empty at the end but is mandatory.
2155 $warnings = array();
2157 // Validate params.
2158 $params = array(
2159 'userid' => $userid
2161 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
2162 $userid = $params['userid'];
2164 // Validate context.
2165 $context = context_system::instance();
2166 self::validate_context($context);
2168 // Check if private messaging between users is allowed.
2169 if (empty($CFG->messaging)) {
2170 throw new moodle_exception('disabled', 'message');
2173 $user = core_user::get_user($userid, '*', MUST_EXIST);
2174 core_user::require_active_user($user);
2176 // Check if we have permissions for retrieve the information.
2177 $capability = 'moodle/site:manageallmessaging';
2178 if (($USER->id != $userid) && !has_capability($capability, $context)) {
2179 throw new required_capability_exception($context, $capability, 'nopermissions', '');
2182 // Now, we can get safely all the blocked users.
2183 $users = \core_message\api::get_blocked_users($user->id);
2185 $blockedusers = array();
2186 foreach ($users as $user) {
2187 $newuser = array(
2188 'id' => $user->id,
2189 'fullname' => fullname($user),
2192 $userpicture = new user_picture($user);
2193 $userpicture->size = 1; // Size f1.
2194 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2196 $blockedusers[] = $newuser;
2199 $results = array(
2200 'users' => $blockedusers,
2201 'warnings' => $warnings
2203 return $results;
2207 * Get blocked users return description.
2209 * @return external_single_structure
2210 * @since 2.9
2212 public static function get_blocked_users_returns() {
2213 return new external_single_structure(
2214 array(
2215 'users' => new external_multiple_structure(
2216 new external_single_structure(
2217 array(
2218 'id' => new external_value(PARAM_INT, 'User ID'),
2219 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2220 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
2223 'List of blocked users'
2225 'warnings' => new external_warnings()
2231 * Returns description of method parameters
2233 * @return external_function_parameters
2234 * @since 2.9
2236 public static function mark_message_read_parameters() {
2237 return new external_function_parameters(
2238 array(
2239 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
2240 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
2241 VALUE_DEFAULT, 0)
2247 * Mark a single message as read, trigger message_viewed event
2249 * @param int $messageid id of the message (in the message table)
2250 * @param int $timeread timestamp for when the message should be marked read
2251 * @return external_description
2252 * @throws invalid_parameter_exception
2253 * @throws moodle_exception
2254 * @since 2.9
2256 public static function mark_message_read($messageid, $timeread) {
2257 global $CFG, $DB, $USER;
2259 // Check if private messaging between users is allowed.
2260 if (empty($CFG->messaging)) {
2261 throw new moodle_exception('disabled', 'message');
2264 // Warnings array, it can be empty at the end but is mandatory.
2265 $warnings = array();
2267 // Validate params.
2268 $params = array(
2269 'messageid' => $messageid,
2270 'timeread' => $timeread
2272 $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
2274 if (empty($params['timeread'])) {
2275 $timeread = time();
2276 } else {
2277 $timeread = $params['timeread'];
2280 // Validate context.
2281 $context = context_system::instance();
2282 self::validate_context($context);
2284 $sql = "SELECT m.*, mcm.userid as useridto
2285 FROM {messages} m
2286 INNER JOIN {message_conversations} mc
2287 ON m.conversationid = mc.id
2288 INNER JOIN {message_conversation_members} mcm
2289 ON mcm.conversationid = mc.id
2290 LEFT JOIN {message_user_actions} mua
2291 ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
2292 WHERE mua.id is NULL
2293 AND mcm.userid != m.useridfrom
2294 AND m.id = ?";
2295 $messageparams = [];
2296 $messageparams[] = $USER->id;
2297 $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
2298 $messageparams[] = $params['messageid'];
2299 $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
2301 if ($message->useridto != $USER->id) {
2302 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
2305 \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
2307 $results = array(
2308 'messageid' => $message->id,
2309 'warnings' => $warnings
2311 return $results;
2315 * Returns description of method result value
2317 * @return external_description
2318 * @since 2.9
2320 public static function mark_message_read_returns() {
2321 return new external_single_structure(
2322 array(
2323 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
2324 'warnings' => new external_warnings()
2330 * Returns description of method parameters
2332 * @return external_function_parameters
2334 public static function mark_notification_read_parameters() {
2335 return new external_function_parameters(
2336 array(
2337 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2338 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
2339 VALUE_DEFAULT, 0)
2345 * Mark a single notification as read.
2347 * This will trigger a 'notification_viewed' event.
2349 * @param int $notificationid id of the notification
2350 * @param int $timeread timestamp for when the notification should be marked read
2351 * @return external_description
2352 * @throws invalid_parameter_exception
2353 * @throws moodle_exception
2355 public static function mark_notification_read($notificationid, $timeread) {
2356 global $CFG, $DB, $USER;
2358 // Check if private messaging between users is allowed.
2359 if (empty($CFG->messaging)) {
2360 throw new moodle_exception('disabled', 'message');
2363 // Warnings array, it can be empty at the end but is mandatory.
2364 $warnings = array();
2366 // Validate params.
2367 $params = array(
2368 'notificationid' => $notificationid,
2369 'timeread' => $timeread
2371 $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
2373 if (empty($params['timeread'])) {
2374 $timeread = time();
2375 } else {
2376 $timeread = $params['timeread'];
2379 // Validate context.
2380 $context = context_system::instance();
2381 self::validate_context($context);
2383 $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
2385 if ($notification->useridto != $USER->id) {
2386 throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
2387 'notification as read');
2390 \core_message\api::mark_notification_as_read($notification, $timeread);
2392 $results = array(
2393 'notificationid' => $notification->id,
2394 'warnings' => $warnings
2397 return $results;
2401 * Returns description of method result value
2403 * @return external_description
2405 public static function mark_notification_read_returns() {
2406 return new external_single_structure(
2407 array(
2408 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2409 'warnings' => new external_warnings()
2415 * Mark all messages as read parameters description.
2417 * @return external_function_parameters
2418 * @since 3.2
2420 public static function mark_all_messages_as_read_parameters() {
2421 return new external_function_parameters(
2422 array(
2423 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2424 'useridfrom' => new external_value(
2425 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2426 VALUE_DEFAULT, 0),
2432 * Mark all notifications as read function.
2434 * @since 3.2
2435 * @throws invalid_parameter_exception
2436 * @throws moodle_exception
2437 * @param int $useridto the user id who received the message
2438 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
2439 * @return external_description
2441 public static function mark_all_messages_as_read($useridto, $useridfrom) {
2442 global $USER, $CFG;
2444 // Check if messaging is enabled.
2445 if (empty($CFG->messaging)) {
2446 throw new moodle_exception('disabled', 'message');
2449 $params = self::validate_parameters(
2450 self::mark_all_messages_as_read_parameters(),
2451 array(
2452 'useridto' => $useridto,
2453 'useridfrom' => $useridfrom,
2457 $context = context_system::instance();
2458 self::validate_context($context);
2460 $useridto = $params['useridto'];
2461 $useridfrom = $params['useridfrom'];
2463 if (!empty($useridto)) {
2464 if (core_user::is_real_user($useridto)) {
2465 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2466 } else {
2467 throw new moodle_exception('invaliduser');
2471 if (!empty($useridfrom)) {
2472 // We use get_user here because the from user can be the noreply or support user.
2473 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2476 // Check if the current user is the sender/receiver or just a privileged user.
2477 if ($useridto != $USER->id and $useridfrom != $USER->id and
2478 // The deleteanymessage cap seems more reasonable here than readallmessages.
2479 !has_capability('moodle/site:deleteanymessage', $context)) {
2480 throw new moodle_exception('accessdenied', 'admin');
2483 if ($useridfrom) {
2484 if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
2485 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
2487 } else {
2488 \core_message\api::mark_all_messages_as_read($useridto);
2491 return true;
2495 * Mark all notifications as read return description.
2497 * @return external_single_structure
2498 * @since 3.2
2500 public static function mark_all_messages_as_read_returns() {
2501 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2505 * Returns description of method parameters.
2507 * @deprecated since 3.6
2508 * @return external_function_parameters
2509 * @since 3.2
2511 public static function delete_conversation_parameters() {
2512 return new external_function_parameters(
2513 array(
2514 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
2515 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
2521 * Deletes a conversation.
2523 * @deprecated since 3.6
2524 * @param int $userid The user id of who we want to delete the conversation for
2525 * @param int $otheruserid The user id of the other user in the conversation
2526 * @return array
2527 * @throws moodle_exception
2528 * @since 3.2
2530 public static function delete_conversation($userid, $otheruserid) {
2531 global $CFG;
2533 // Check if private messaging between users is allowed.
2534 if (empty($CFG->messaging)) {
2535 throw new moodle_exception('disabled', 'message');
2538 // Warnings array, it can be empty at the end but is mandatory.
2539 $warnings = array();
2541 // Validate params.
2542 $params = array(
2543 'userid' => $userid,
2544 'otheruserid' => $otheruserid,
2546 $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
2548 // Validate context.
2549 $context = context_system::instance();
2550 self::validate_context($context);
2552 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2553 core_user::require_active_user($user);
2555 if (!$conversationid = \core_message\api::get_conversation_between_users([$userid, $otheruserid])) {
2556 return [];
2559 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
2560 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
2561 $status = true;
2562 } else {
2563 throw new moodle_exception('You do not have permission to delete messages');
2566 $results = array(
2567 'status' => $status,
2568 'warnings' => $warnings
2571 return $results;
2575 * Returns description of method result value.
2577 * @deprecated since 3.6
2578 * @return external_description
2579 * @since 3.2
2581 public static function delete_conversation_returns() {
2582 return new external_single_structure(
2583 array(
2584 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
2585 'warnings' => new external_warnings()
2591 * Marking the method as deprecated.
2593 * @return bool
2595 public static function delete_conversation_is_deprecated() {
2596 return true;
2600 * Returns description of method parameters.
2602 * @return external_function_parameters
2603 * @since 3.6
2605 public static function delete_conversations_by_id_parameters() {
2606 return new external_function_parameters(
2607 array(
2608 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
2609 'conversationids' => new external_multiple_structure(
2610 new external_value(PARAM_INT, 'The id of the conversation'),
2611 'List of conversation IDs'
2618 * Deletes a conversation.
2620 * @param int $userid The user id of who we want to delete the conversation for
2621 * @param int[] $conversationids The ids of the conversations
2622 * @return array
2623 * @throws moodle_exception
2624 * @since 3.6
2626 public static function delete_conversations_by_id($userid, array $conversationids) {
2627 global $CFG;
2629 // Check if private messaging between users is allowed.
2630 if (empty($CFG->messaging)) {
2631 throw new moodle_exception('disabled', 'message');
2634 // Validate params.
2635 $params = [
2636 'userid' => $userid,
2637 'conversationids' => $conversationids,
2639 $params = self::validate_parameters(self::delete_conversations_by_id_parameters(), $params);
2641 // Validate context.
2642 $context = context_system::instance();
2643 self::validate_context($context);
2645 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2646 core_user::require_active_user($user);
2648 foreach ($conversationids as $conversationid) {
2649 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
2650 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
2651 } else {
2652 throw new moodle_exception("You do not have permission to delete the conversation '$conversationid'");
2656 return [];
2660 * Returns description of method result value.
2662 * @return external_description
2663 * @since 3.6
2665 public static function delete_conversations_by_id_returns() {
2666 return new external_warnings();
2670 * Returns description of method parameters
2672 * @return external_function_parameters
2673 * @since 3.1
2675 public static function delete_message_parameters() {
2676 return new external_function_parameters(
2677 array(
2678 'messageid' => new external_value(PARAM_INT, 'The message id'),
2679 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
2680 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
2686 * Deletes a message
2688 * @param int $messageid the message id
2689 * @param int $userid the user id of who we want to delete the message for
2690 * @param bool $read if is a message read (default to true)
2691 * @return external_description
2692 * @throws moodle_exception
2693 * @since 3.1
2695 public static function delete_message($messageid, $userid, $read = true) {
2696 global $CFG;
2698 // Check if private messaging between users is allowed.
2699 if (empty($CFG->messaging)) {
2700 throw new moodle_exception('disabled', 'message');
2703 // Warnings array, it can be empty at the end but is mandatory.
2704 $warnings = array();
2706 // Validate params.
2707 $params = array(
2708 'messageid' => $messageid,
2709 'userid' => $userid,
2710 'read' => $read
2712 $params = self::validate_parameters(self::delete_message_parameters(), $params);
2714 // Validate context.
2715 $context = context_system::instance();
2716 self::validate_context($context);
2718 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2719 core_user::require_active_user($user);
2721 if (\core_message\api::can_delete_message($user->id, $messageid)) {
2722 $status = \core_message\api::delete_message($user->id, $messageid);
2723 } else {
2724 throw new moodle_exception('You do not have permission to delete this message');
2727 $results = array(
2728 'status' => $status,
2729 'warnings' => $warnings
2731 return $results;
2735 * Returns description of method result value
2737 * @return external_description
2738 * @since 3.1
2740 public static function delete_message_returns() {
2741 return new external_single_structure(
2742 array(
2743 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
2744 'warnings' => new external_warnings()
2750 * Returns description of method parameters
2752 * @return external_function_parameters
2753 * @since 3.2
2755 public static function message_processor_config_form_parameters() {
2756 return new external_function_parameters(
2757 array(
2758 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
2759 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
2760 'formvalues' => new external_multiple_structure(
2761 new external_single_structure(
2762 array(
2763 'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
2764 'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
2767 'Config form values',
2768 VALUE_REQUIRED
2775 * Processes a message processor config form.
2777 * @param int $userid the user id
2778 * @param string $name the name of the processor
2779 * @param array $formvalues the form values
2780 * @return external_description
2781 * @throws moodle_exception
2782 * @since 3.2
2784 public static function message_processor_config_form($userid, $name, $formvalues) {
2785 global $USER, $CFG;
2787 // Check if messaging is enabled.
2788 if (empty($CFG->messaging)) {
2789 throw new moodle_exception('disabled', 'message');
2792 $params = self::validate_parameters(
2793 self::message_processor_config_form_parameters(),
2794 array(
2795 'userid' => $userid,
2796 'name' => $name,
2797 'formvalues' => $formvalues,
2801 $user = self::validate_preferences_permissions($params['userid']);
2803 $processor = get_message_processor($name);
2804 $preferences = [];
2805 $form = new stdClass();
2807 foreach ($formvalues as $formvalue) {
2808 // Curly braces to ensure interpretation is consistent between
2809 // php 5 and php 7.
2810 $form->{$formvalue['name']} = $formvalue['value'];
2813 $processor->process_form($form, $preferences);
2815 if (!empty($preferences)) {
2816 set_user_preferences($preferences, $userid);
2821 * Returns description of method result value
2823 * @return external_description
2824 * @since 3.2
2826 public static function message_processor_config_form_returns() {
2827 return null;
2831 * Returns description of method parameters
2833 * @return external_function_parameters
2834 * @since 3.2
2836 public static function get_message_processor_parameters() {
2837 return new external_function_parameters(
2838 array(
2839 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
2840 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
2846 * Get a message processor.
2848 * @param int $userid
2849 * @param string $name the name of the processor
2850 * @return external_description
2851 * @throws moodle_exception
2852 * @since 3.2
2854 public static function get_message_processor($userid = 0, $name) {
2855 global $USER, $PAGE, $CFG;
2857 // Check if messaging is enabled.
2858 if (empty($CFG->messaging)) {
2859 throw new moodle_exception('disabled', 'message');
2862 $params = self::validate_parameters(
2863 self::get_message_processor_parameters(),
2864 array(
2865 'userid' => $userid,
2866 'name' => $name,
2870 if (empty($params['userid'])) {
2871 $params['userid'] = $USER->id;
2874 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2875 core_user::require_active_user($user);
2876 self::validate_context(context_user::instance($params['userid']));
2878 $processor = get_message_processor($name);
2880 $processoroutput = new \core_message\output\processor($processor, $user);
2881 $renderer = $PAGE->get_renderer('core_message');
2883 return $processoroutput->export_for_template($renderer);
2887 * Returns description of method result value
2889 * @return external_description
2890 * @since 3.2
2892 public static function get_message_processor_returns() {
2893 return new external_function_parameters(
2894 array(
2895 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
2896 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
2902 * Check that the user has enough permission to retrieve message or notifications preferences.
2904 * @param int $userid the user id requesting the preferences
2905 * @return stdClass full user object
2906 * @throws moodle_exception
2907 * @since Moodle 3.2
2909 protected static function validate_preferences_permissions($userid) {
2910 global $USER;
2912 if (empty($userid)) {
2913 $user = $USER;
2914 } else {
2915 $user = core_user::get_user($userid, '*', MUST_EXIST);
2916 core_user::require_active_user($user);
2919 $systemcontext = context_system::instance();
2920 self::validate_context($systemcontext);
2922 // Check access control.
2923 if ($user->id == $USER->id) {
2924 // Editing own message profile.
2925 require_capability('moodle/user:editownmessageprofile', $systemcontext);
2926 } else {
2927 // Teachers, parents, etc.
2928 $personalcontext = context_user::instance($user->id);
2929 require_capability('moodle/user:editmessageprofile', $personalcontext);
2931 return $user;
2935 * Returns a notification or message preference structure.
2937 * @return external_single_structure the structure
2938 * @since Moodle 3.2
2940 protected static function get_preferences_structure() {
2941 return new external_single_structure(
2942 array(
2943 'userid' => new external_value(PARAM_INT, 'User id'),
2944 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
2945 'processors' => new external_multiple_structure(
2946 new external_single_structure(
2947 array(
2948 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2949 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2950 'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
2951 'contextid' => new external_value(PARAM_INT, 'Context id'),
2952 'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
2955 'Config form values'
2957 'components' => new external_multiple_structure(
2958 new external_single_structure(
2959 array(
2960 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2961 'notifications' => new external_multiple_structure(
2962 new external_single_structure(
2963 array(
2964 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2965 'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
2966 'processors' => new external_multiple_structure(
2967 new external_single_structure(
2968 array(
2969 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2970 'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2971 'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
2972 'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
2973 'loggedin' => new external_single_structure(
2974 array(
2975 'name' => new external_value(PARAM_NOTAGS, 'Name'),
2976 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2977 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2980 'loggedoff' => new external_single_structure(
2981 array(
2982 'name' => new external_value(PARAM_NOTAGS, 'Name'),
2983 'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2984 'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2989 'Processors values for this notification'
2993 'List of notificaitons for the component'
2997 'Available components'
3004 * Returns description of method parameters
3006 * @return external_function_parameters
3007 * @since 3.2
3009 public static function get_user_notification_preferences_parameters() {
3010 return new external_function_parameters(
3011 array(
3012 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
3018 * Get the notification preferences for a given user.
3020 * @param int $userid id of the user, 0 for current user
3021 * @return external_description
3022 * @throws moodle_exception
3023 * @since 3.2
3025 public static function get_user_notification_preferences($userid = 0) {
3026 global $PAGE;
3028 $params = self::validate_parameters(
3029 self::get_user_notification_preferences_parameters(),
3030 array(
3031 'userid' => $userid,
3034 $user = self::validate_preferences_permissions($params['userid']);
3036 $processors = get_message_processors();
3037 $providers = message_get_providers_for_user($user->id);
3038 $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
3039 $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
3041 $renderer = $PAGE->get_renderer('core_message');
3043 $result = array(
3044 'warnings' => array(),
3045 'preferences' => $notificationlist->export_for_template($renderer)
3047 return $result;
3051 * Returns description of method result value
3053 * @return external_description
3054 * @since 3.2
3056 public static function get_user_notification_preferences_returns() {
3057 return new external_function_parameters(
3058 array(
3059 'preferences' => self::get_preferences_structure(),
3060 'warnings' => new external_warnings(),
3066 * Returns description of method parameters
3068 * @return external_function_parameters
3069 * @since 3.2
3071 public static function get_user_message_preferences_parameters() {
3072 return new external_function_parameters(
3073 array(
3074 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
3080 * Get the notification preferences for a given user.
3082 * @param int $userid id of the user, 0 for current user
3083 * @return external_description
3084 * @throws moodle_exception
3085 * @since 3.2
3087 public static function get_user_message_preferences($userid = 0) {
3088 global $PAGE;
3090 $params = self::validate_parameters(
3091 self::get_user_message_preferences_parameters(),
3092 array(
3093 'userid' => $userid,
3097 $user = self::validate_preferences_permissions($params['userid']);
3099 // Filter out enabled, available system_configured and user_configured processors only.
3100 $readyprocessors = array_filter(get_message_processors(), function($processor) {
3101 return $processor->enabled &&
3102 $processor->configured &&
3103 $processor->object->is_user_configured() &&
3104 // Filter out processors that don't have and message preferences to configure.
3105 $processor->object->has_message_preferences();
3108 $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
3109 return $provider->component === 'moodle';
3111 $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
3112 $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
3113 $providers, $preferences, $user);
3115 $renderer = $PAGE->get_renderer('core_message');
3117 $result = array(
3118 'warnings' => array(),
3119 'preferences' => $notificationlistoutput->export_for_template($renderer),
3120 'blocknoncontacts' => \core_message\api::get_user_privacy_messaging_preference($user->id),
3122 return $result;
3126 * Returns description of method result value
3128 * @return external_description
3129 * @since 3.2
3131 public static function get_user_message_preferences_returns() {
3132 return new external_function_parameters(
3133 array(
3134 'preferences' => self::get_preferences_structure(),
3135 'blocknoncontacts' => new external_value(PARAM_INT, 'Privacy messaging setting to define who can message you'),
3136 'warnings' => new external_warnings(),
3142 * Returns description of method parameters for the favourite_conversations() method.
3144 * @return external_function_parameters
3146 public static function set_favourite_conversations_parameters() {
3147 return new external_function_parameters(
3148 array(
3149 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0),
3150 'conversations' => new external_multiple_structure(
3151 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0)
3158 * Favourite a conversation, or list of conversations for a user.
3160 * @param int $userid the id of the user, or 0 for the current user.
3161 * @param array $conversationids the list of conversations ids to favourite.
3162 * @return array
3163 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
3165 public static function set_favourite_conversations(int $userid, array $conversationids) {
3166 global $CFG, $USER;
3168 // All the business logic checks that really shouldn't be in here.
3169 if (empty($CFG->messaging)) {
3170 throw new moodle_exception('disabled', 'message');
3172 $params = [
3173 'userid' => $userid,
3174 'conversations' => $conversationids
3176 $params = self::validate_parameters(self::set_favourite_conversations_parameters(), $params);
3177 $systemcontext = context_system::instance();
3178 self::validate_context($systemcontext);
3180 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
3181 throw new moodle_exception('You do not have permission to perform this action.');
3184 foreach ($params['conversations'] as $conversationid) {
3185 \core_message\api::set_favourite_conversation($conversationid, $params['userid']);
3188 return [];
3192 * Return a description of the returns for the create_user_favourite_conversations() method.
3194 * @return external_description
3196 public static function set_favourite_conversations_returns() {
3197 return new external_warnings();
3201 * Returns description of method parameters for unfavourite_conversations() method.
3203 * @return external_function_parameters
3205 public static function unset_favourite_conversations_parameters() {
3206 return new external_function_parameters(
3207 array(
3208 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0),
3209 'conversations' => new external_multiple_structure(
3210 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0)
3217 * Unfavourite a conversation, or list of conversations for a user.
3219 * @param int $userid the id of the user, or 0 for the current user.
3220 * @param array $conversationids the list of conversations ids unset as favourites.
3221 * @return array
3222 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action.
3224 public static function unset_favourite_conversations(int $userid, array $conversationids) {
3225 global $CFG, $USER;
3227 // All the business logic checks that really shouldn't be in here.
3228 if (empty($CFG->messaging)) {
3229 throw new moodle_exception('disabled', 'message');
3231 $params = [
3232 'userid' => $userid,
3233 'conversations' => $conversationids
3235 $params = self::validate_parameters(self::unset_favourite_conversations_parameters(), $params);
3236 $systemcontext = context_system::instance();
3237 self::validate_context($systemcontext);
3239 if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
3240 throw new moodle_exception('You do not have permission to perform this action.');
3243 foreach ($params['conversations'] as $conversationid) {
3244 \core_message\api::unset_favourite_conversation($conversationid, $params['userid']);
3247 return [];
3251 * Unset favourite conversations return description.
3253 * @return external_description
3255 public static function unset_favourite_conversations_returns() {
3256 return new external_warnings();