MDL-63303 message: add fields to send_instant_message
[moodle.git] / message / externallib.php
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.
13 //
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
20  *
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
25  */
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
34  *
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
40  */
41 class core_message_external extends external_api {
42     /**
43      * Returns description of method parameters
44      *
45      * @return external_function_parameters
46      * @since Moodle 3.6
47      */
48     public static function send_messages_to_conversation_parameters() {
49         return new external_function_parameters(
50             array(
51                 'conversationid' => new external_value(PARAM_INT, 'id of the conversation'),
52                 'messages' => new external_multiple_structure(
53                     new external_single_structure(
54                         array(
55                             'text' => new external_value(PARAM_RAW, 'the text of the message'),
56                             'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
57                         )
58                     )
59                 )
60             )
61         );
62     }
64     /**
65      * Send messages from the current USER to a conversation.
66      *
67      * This conversation may be any type of conversation, individual or group.
68      *
69      * @param int $conversationid the id of the conversation to which the messages will be sent.
70      * @param array $messages An array of message to send.
71      * @return array the array of messages which were sent (created).
72      * @since Moodle 3.6
73      */
74     public static function send_messages_to_conversation(int $conversationid, array $messages = []) {
75         global $CFG, $USER;
77         // Check if messaging is enabled.
78         if (empty($CFG->messaging)) {
79             throw new moodle_exception('disabled', 'message');
80         }
82         // Ensure the current user is allowed to run this function.
83         $context = context_system::instance();
84         self::validate_context($context);
86         $params = self::validate_parameters(self::send_messages_to_conversation_parameters(), [
87             'conversationid' => $conversationid,
88             'messages' => $messages
89         ]);
91         $messages = [];
92         foreach ($params['messages'] as $message) {
93             $messages[] = \core_message\api::send_message_to_conversation($USER->id, $params['conversationid'], $message['text'],
94                 $message['textformat']);
95         }
97         return $messages;
98     }
100     /**
101      * Returns description of method result value.
102      *
103      * @return external_description
104      * @since Moodle 3.6
105      */
106     public static function send_messages_to_conversation_returns() {
107         return new external_multiple_structure(
108             self::get_conversation_message_structure()
109         );
110     }
113     /**
114      * Returns description of method parameters
115      *
116      * @return external_function_parameters
117      * @since Moodle 2.2
118      */
119     public static function send_instant_messages_parameters() {
120         return new external_function_parameters(
121             array(
122                 'messages' => new external_multiple_structure(
123                     new external_single_structure(
124                         array(
125                             'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
126                             'text' => new external_value(PARAM_RAW, 'the text of the message'),
127                             'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
128                             'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own client id for the message. If this id is provided, the fail message id will be returned to you', VALUE_OPTIONAL),
129                         )
130                     )
131                 )
132             )
133         );
134     }
136     /**
137      * Send private messages from the current USER to other users
138      *
139      * @param array $messages An array of message to send.
140      * @return array
141      * @since Moodle 2.2
142      */
143     public static function send_instant_messages($messages = array()) {
144         global $CFG, $USER, $DB;
146         // Check if messaging is enabled.
147         if (empty($CFG->messaging)) {
148             throw new moodle_exception('disabled', 'message');
149         }
151         // Ensure the current user is allowed to run this function
152         $context = context_system::instance();
153         self::validate_context($context);
154         require_capability('moodle/site:sendmessage', $context);
156         $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
158         //retrieve all tousers of the messages
159         $receivers = array();
160         foreach($params['messages'] as $message) {
161             $receivers[] = $message['touserid'];
162         }
163         list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers);
164         $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
166         $resultmessages = array();
167         $messageids = array();
168         foreach ($params['messages'] as $message) {
169             $resultmsg = array(); //the infos about the success of the operation
171             // We are going to do some checking.
172             // Code should match /messages/index.php checks.
173             $success = true;
175             // Check the user exists.
176             if (empty($tousers[$message['touserid']])) {
177                 $success = false;
178                 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
179             }
181             // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
182             // Check if the recipient can be messaged by the sender.
183             if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
184                 $success = false;
185                 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
186             }
188             // Now we can send the message (at least try).
189             if ($success) {
190                 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
191                 $success = message_post_message($USER, $tousers[$message['touserid']],
192                         $message['text'], external_validate_format($message['textformat']));
193             }
195             // Build the resultmsg.
196             if (isset($message['clientmsgid'])) {
197                 $resultmsg['clientmsgid'] = $message['clientmsgid'];
198             }
199             if ($success) {
200                 $resultmsg['msgid'] = $success;
201                 $resultmsg['text'] = message_format_message_text((object) [
202                     'smallmessage' => $message['text'],
203                     'fullmessageformat' => external_validate_format($message['textformat'])
204                 ]);
205                 $resultmsg['timecreated'] = time();
206                 $messageids[] = $success;
207             } else {
208                 // WARNINGS: for backward compatibility we return this errormessage.
209                 //          We should have thrown exceptions as these errors prevent results to be returned.
210                 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
211                 $resultmsg['msgid'] = -1;
212                 $resultmsg['errormessage'] = $errormessage;
213             }
215             $resultmessages[] = $resultmsg;
216         }
218         if (!empty($messageids)) {
219             $messagerecords = $DB->get_records_list('messages', 'id', $messageids, '', 'id, conversationid');
220             $resultmessages = array_map(function($resultmessage) use ($messagerecords, $USER) {
221                 $id = $resultmessage['msgid'];
222                 $resultmessage['conversationid'] = isset($messagerecords[$id]) ? $messagerecords[$id]->conversationid : null;
223                 $resultmessage['useridfrom'] = $USER->id;
224                 return $resultmessage;
225             }, $resultmessages);
226         }
228         return $resultmessages;
229     }
231     /**
232      * Returns description of method result value
233      *
234      * @return external_description
235      * @since Moodle 2.2
236      */
237     public static function send_instant_messages_returns() {
238         return new external_multiple_structure(
239             new external_single_structure(
240                 array(
241                     'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds:  id of the created message if it succeeded, -1 when failed'),
242                     'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
243                     'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL),
244                     'text' => new external_value(PARAM_RAW, 'The text of the message', VALUE_OPTIONAL),
245                     'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message', VALUE_OPTIONAL),
246                     'conversationid' => new external_value(PARAM_INT, 'The conversation id for this message', VALUE_OPTIONAL),
247                     'useridfrom' => new external_value(PARAM_INT, 'The user id who sent the message', VALUE_OPTIONAL),
248                 )
249             )
250         );
251     }
253     /**
254      * Create contacts parameters description.
255      *
256      * @deprecated since Moodle 3.6
257      * @return external_function_parameters
258      * @since Moodle 2.5
259      */
260     public static function create_contacts_parameters() {
261         return new external_function_parameters(
262             array(
263                 'userids' => new external_multiple_structure(
264                     new external_value(PARAM_INT, 'User ID'),
265                     'List of user IDs'
266                 ),
267                 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
268                     current user', VALUE_DEFAULT, 0)
269             )
270         );
271     }
273     /**
274      * Create contacts.
275      *
276      * @deprecated since Moodle 3.6
277      * @param array $userids array of user IDs.
278      * @param int $userid The id of the user we are creating the contacts for
279      * @return external_description
280      * @since Moodle 2.5
281      */
282     public static function create_contacts($userids, $userid = 0) {
283         global $CFG, $USER;
285         // Check if messaging is enabled.
286         if (empty($CFG->messaging)) {
287             throw new moodle_exception('disabled', 'message');
288         }
290         if (empty($userid)) {
291             $userid = $USER->id;
292         }
294         // Validate context.
295         $context = context_system::instance();
296         self::validate_context($context);
298         $params = array('userids' => $userids, 'userid' => $userid);
299         $params = self::validate_parameters(self::create_contacts_parameters(), $params);
301         $capability = 'moodle/site:manageallmessaging';
302         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
303             throw new required_capability_exception($context, $capability, 'nopermissions', '');
304         }
306         $warnings = array();
307         foreach ($params['userids'] as $id) {
308             if (!message_add_contact($id, 0, $params['userid'])) {
309                 $warnings[] = array(
310                     'item' => 'user',
311                     'itemid' => $id,
312                     'warningcode' => 'contactnotcreated',
313                     'message' => 'The contact could not be created'
314                 );
315             }
316         }
317         return $warnings;
318     }
320     /**
321      * Create contacts return description.
322      *
323      * @deprecated since Moodle 3.6
324      * @return external_description
325      * @since Moodle 2.5
326      */
327     public static function create_contacts_returns() {
328         return new external_warnings();
329     }
331     /**
332      * Marking the method as deprecated.
333      *
334      * @return bool
335      */
336     public static function create_contacts_is_deprecated() {
337         return true;
338     }
340     /**
341      * Delete contacts parameters description.
342      *
343      * @return external_function_parameters
344      * @since Moodle 2.5
345      */
346     public static function delete_contacts_parameters() {
347         return new external_function_parameters(
348             array(
349                 'userids' => new external_multiple_structure(
350                     new external_value(PARAM_INT, 'User ID'),
351                     'List of user IDs'
352                 ),
353                 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
354                     current user', VALUE_DEFAULT, 0)
355             )
356         );
357     }
359     /**
360      * Delete contacts.
361      *
362      * @param array $userids array of user IDs.
363      * @param int $userid The id of the user we are deleting the contacts for
364      * @return null
365      * @since Moodle 2.5
366      */
367     public static function delete_contacts($userids, $userid = 0) {
368         global $CFG, $USER;
370         // Check if messaging is enabled.
371         if (empty($CFG->messaging)) {
372             throw new moodle_exception('disabled', 'message');
373         }
375         if (empty($userid)) {
376             $userid = $USER->id;
377         }
379         // Validate context.
380         $context = context_system::instance();
381         self::validate_context($context);
383         $params = array('userids' => $userids, 'userid' => $userid);
384         $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
386         $capability = 'moodle/site:manageallmessaging';
387         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
388             throw new required_capability_exception($context, $capability, 'nopermissions', '');
389         }
391         foreach ($params['userids'] as $id) {
392             \core_message\api::remove_contact($params['userid'], $id);
393         }
395         return null;
396     }
398     /**
399      * Delete contacts return description.
400      *
401      * @return external_description
402      * @since Moodle 2.5
403      */
404     public static function delete_contacts_returns() {
405         return null;
406     }
408     /**
409      * Block user parameters description.
410      *
411      * @return external_function_parameters
412      */
413     public static function block_user_parameters() {
414         return new external_function_parameters(
415             [
416                 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
417                 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
418             ]
419         );
420     }
422     /**
423      * Blocks a user.
424      *
425      * @param int $userid The id of the user who is blocking
426      * @param int $blockeduserid The id of the user being blocked
427      * @return external_description
428      */
429     public static function block_user(int $userid, int $blockeduserid) {
430         global $CFG, $USER;
432         // Check if messaging is enabled.
433         if (empty($CFG->messaging)) {
434             throw new moodle_exception('disabled', 'message');
435         }
437         // Validate context.
438         $context = context_system::instance();
439         self::validate_context($context);
441         $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
442         $params = self::validate_parameters(self::block_user_parameters(), $params);
444         $capability = 'moodle/site:manageallmessaging';
445         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
446             throw new required_capability_exception($context, $capability, 'nopermissions', '');
447         }
449         if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
450             \core_message\api::block_user($params['userid'], $params['blockeduserid']);
451         }
453         return [];
454     }
456     /**
457      * Block user return description.
458      *
459      * @return external_description
460      */
461     public static function block_user_returns() {
462         return new external_warnings();
463     }
465     /**
466      * Unblock user parameters description.
467      *
468      * @return external_function_parameters
469      */
470     public static function unblock_user_parameters() {
471         return new external_function_parameters(
472             [
473                 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
474                 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
475             ]
476         );
477     }
479     /**
480      * Unblock user.
481      *
482      * @param int $userid The id of the user who is unblocking
483      * @param int $unblockeduserid The id of the user being unblocked
484      */
485     public static function unblock_user(int $userid, int $unblockeduserid) {
486         global $CFG, $USER;
488         // Check if messaging is enabled.
489         if (empty($CFG->messaging)) {
490             throw new moodle_exception('disabled', 'message');
491         }
493         // Validate context.
494         $context = context_system::instance();
495         self::validate_context($context);
497         $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
498         $params = self::validate_parameters(self::unblock_user_parameters(), $params);
500         $capability = 'moodle/site:manageallmessaging';
501         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
502             throw new required_capability_exception($context, $capability, 'nopermissions', '');
503         }
505         \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
507         return [];
508     }
510     /**
511      * Unblock user return description.
512      *
513      * @return external_description
514      */
515     public static function unblock_user_returns() {
516         return new external_warnings();
517     }
519     /**
520      * Block contacts parameters description.
521      *
522      * @deprecated since Moodle 3.6
523      * @return external_function_parameters
524      * @since Moodle 2.5
525      */
526     public static function block_contacts_parameters() {
527         return new external_function_parameters(
528             array(
529                 'userids' => new external_multiple_structure(
530                     new external_value(PARAM_INT, 'User ID'),
531                     'List of user IDs'
532                 ),
533                 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
534                     current user', VALUE_DEFAULT, 0)
535             )
536         );
537     }
539     /**
540      * Block contacts.
541      *
542      * @deprecated since Moodle 3.6
543      * @param array $userids array of user IDs.
544      * @param int $userid The id of the user we are blocking the contacts for
545      * @return external_description
546      * @since Moodle 2.5
547      */
548     public static function block_contacts($userids, $userid = 0) {
549         global $CFG, $USER;
551         // Check if messaging is enabled.
552         if (empty($CFG->messaging)) {
553             throw new moodle_exception('disabled', 'message');
554         }
556         if (empty($userid)) {
557             $userid = $USER->id;
558         }
560         // Validate context.
561         $context = context_system::instance();
562         self::validate_context($context);
564         $params = array('userids' => $userids, 'userid' => $userid);
565         $params = self::validate_parameters(self::block_contacts_parameters(), $params);
567         $capability = 'moodle/site:manageallmessaging';
568         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
569             throw new required_capability_exception($context, $capability, 'nopermissions', '');
570         }
572         $warnings = array();
573         foreach ($params['userids'] as $id) {
574             if (!message_block_contact($id, $params['userid'])) {
575                 $warnings[] = array(
576                     'item' => 'user',
577                     'itemid' => $id,
578                     'warningcode' => 'contactnotblocked',
579                     'message' => 'The contact could not be blocked'
580                 );
581             }
582         }
583         return $warnings;
584     }
586     /**
587      * Block contacts return description.
588      *
589      * @deprecated since Moodle 3.6
590      * @return external_description
591      * @since Moodle 2.5
592      */
593     public static function block_contacts_returns() {
594         return new external_warnings();
595     }
597     /**
598      * Marking the method as deprecated.
599      *
600      * @return bool
601      */
602     public static function block_contacts_is_deprecated() {
603         return true;
604     }
606     /**
607      * Unblock contacts parameters description.
608      *
609      * @deprecated since Moodle 3.6
610      * @return external_function_parameters
611      * @since Moodle 2.5
612      */
613     public static function unblock_contacts_parameters() {
614         return new external_function_parameters(
615             array(
616                 'userids' => new external_multiple_structure(
617                     new external_value(PARAM_INT, 'User ID'),
618                     'List of user IDs'
619                 ),
620                 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
621                     current user', VALUE_DEFAULT, 0)
622             )
623         );
624     }
626     /**
627      * Unblock contacts.
628      *
629      * @param array $userids array of user IDs.
630      * @param int $userid The id of the user we are unblocking the contacts for
631      * @return null
632      * @since Moodle 2.5
633      */
634     public static function unblock_contacts($userids, $userid = 0) {
635         global $CFG, $USER;
637         // Check if messaging is enabled.
638         if (empty($CFG->messaging)) {
639             throw new moodle_exception('disabled', 'message');
640         }
642         if (empty($userid)) {
643             $userid = $USER->id;
644         }
646         // Validate context.
647         $context = context_system::instance();
648         self::validate_context($context);
650         $params = array('userids' => $userids, 'userid' => $userid);
651         $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
653         $capability = 'moodle/site:manageallmessaging';
654         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
655             throw new required_capability_exception($context, $capability, 'nopermissions', '');
656         }
658         foreach ($params['userids'] as $id) {
659             message_unblock_contact($id, $params['userid']);
660         }
662         return null;
663     }
665     /**
666      * Unblock contacts return description.
667      *
668      * @deprecated since Moodle 3.6
669      * @return external_description
670      * @since Moodle 2.5
671      */
672     public static function unblock_contacts_returns() {
673         return null;
674     }
676     /**
677      * Marking the method as deprecated.
678      *
679      * @return bool
680      */
681     public static function unblock_contacts_is_deprecated() {
682         return true;
683     }
685     /**
686      * Returns contact requests parameters description.
687      *
688      * @return external_function_parameters
689      */
690     public static function get_contact_requests_parameters() {
691         return new external_function_parameters(
692             [
693                 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for'),
694                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
695                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
696             ]
697         );
698     }
700     /**
701      * Handles returning the contact requests for a user.
702      *
703      * This also includes the user data necessary to display information
704      * about the user.
705      *
706      * It will not include blocked users.
707      *
708      * @param int $userid The id of the user we want to get the contact requests for
709      * @param int $limitfrom
710      * @param int $limitnum
711      */
712     public static function get_contact_requests(int $userid, int $limitfrom = 0, int $limitnum = 0) {
713         global $CFG, $USER;
715         // Check if messaging is enabled.
716         if (empty($CFG->messaging)) {
717             throw new moodle_exception('disabled', 'message');
718         }
720         // Validate context.
721         $context = context_system::instance();
722         self::validate_context($context);
724         $params = [
725             'userid' => $userid,
726             'limitfrom' => $limitfrom,
727             'limitnum' => $limitnum
728         ];
729         $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
731         $capability = 'moodle/site:manageallmessaging';
732         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
733             throw new required_capability_exception($context, $capability, 'nopermissions', '');
734         }
736         return \core_message\api::get_contact_requests($params['userid'], $params['limitfrom'], $params['limitnum']);
737     }
739     /**
740      * Returns the contact requests return description.
741      *
742      * @return external_description
743      */
744     public static function get_contact_requests_returns() {
745         return new external_multiple_structure(
746             self::get_conversation_member_structure()
747         );
748     }
750     /**
751      * Returns get conversation members parameters description.
752      *
753      * @return external_function_parameters
754      */
755     public static function get_conversation_members_parameters() {
756         return new external_function_parameters(
757             [
758                 'userid' => new external_value(PARAM_INT, 'The id of the user we are performing this action on behalf of'),
759                 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation'),
760                 'includecontactrequests' => new external_value(PARAM_BOOL, 'Do we want to include contact requests?',
761                     VALUE_DEFAULT, false),
762                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
763                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
764             ]
765         );
766     }
768     /**
769      * Returns a list of conversation members.
770      *
771      * @param int $userid The user we are returning the conversation members for, used by helper::get_member_info.
772      * @param int $conversationid The id of the conversation
773      * @param bool $includecontactrequests Do we want to include contact requests with this data?
774      * @param int $limitfrom
775      * @param int $limitnum
776      * @return array
777      */
778     public static function get_conversation_members(int $userid, int $conversationid, bool $includecontactrequests = false,
779                                                     int $limitfrom = 0, int $limitnum = 0) {
780         global $CFG, $USER;
782         // Check if messaging is enabled.
783         if (empty($CFG->messaging)) {
784             throw new moodle_exception('disabled', 'message');
785         }
787         // Validate context.
788         $context = context_system::instance();
789         self::validate_context($context);
791         $params = [
792             'userid' => $userid,
793             'conversationid' => $conversationid,
794             'includecontactrequests' => $includecontactrequests,
795             'limitfrom' => $limitfrom,
796             'limitnum' => $limitnum
797         ];
798         $params = self::validate_parameters(self::get_conversation_members_parameters(), $params);
800         $capability = 'moodle/site:manageallmessaging';
801         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
802             throw new required_capability_exception($context, $capability, 'nopermissions', '');
803         }
805         // The user needs to be a part of the conversation before querying who the members are.
806         if (!\core_message\api::is_user_in_conversation($params['userid'], $params['conversationid'])) {
807             throw new moodle_exception('You are not a member of this conversation.');
808         }
811         return \core_message\api::get_conversation_members($params['userid'], $params['conversationid'], $params['includecontactrequests'],
812             $params['limitfrom'], $params['limitnum']);
813     }
815     /**
816      * Returns the get conversation members return description.
817      *
818      * @return external_description
819      */
820     public static function get_conversation_members_returns() {
821         return new external_multiple_structure(
822             self::get_conversation_member_structure(true)
823         );
824     }
826     /**
827      * Creates a contact request parameters description.
828      *
829      * @return external_function_parameters
830      */
831     public static function create_contact_request_parameters() {
832         return new external_function_parameters(
833             [
834                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
835                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
836             ]
837         );
838     }
840     /**
841      * Creates a contact request.
842      *
843      * @param int $userid The id of the user who is creating the contact request
844      * @param int $requesteduserid The id of the user being requested
845      */
846     public static function create_contact_request(int $userid, int $requesteduserid) {
847         global $CFG, $USER;
849         // Check if messaging is enabled.
850         if (empty($CFG->messaging)) {
851             throw new moodle_exception('disabled', 'message');
852         }
854         // Validate context.
855         $context = context_system::instance();
856         self::validate_context($context);
858         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
859         $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
861         $capability = 'moodle/site:manageallmessaging';
862         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
863             throw new required_capability_exception($context, $capability, 'nopermissions', '');
864         }
866         $result = [
867             'warnings' => []
868         ];
870         if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
871             $result['warnings'][] = [
872                 'item' => 'user',
873                 'itemid' => $params['requesteduserid'],
874                 'warningcode' => 'cannotcreatecontactrequest',
875                 'message' => 'You are unable to create a contact request for this user'
876             ];
877         } else {
878             if ($requests = \core_message\api::get_contact_requests_between_users($params['userid'], $params['requesteduserid'])) {
879                 // There should only ever be one but just in case there are multiple then we can return the first.
880                 $result['request'] = array_shift($requests);
881             } else {
882                 $result['request'] = \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
883             }
884         }
886         return $result;
887     }
889     /**
890      * Creates a contact request return description.
891      *
892      * @return external_description
893      */
894     public static function create_contact_request_returns() {
895         return new external_single_structure(
896             array(
897                 'request' => new external_single_structure(
898                     array(
899                         'id' => new external_value(PARAM_INT, 'Message id'),
900                         'userid' => new external_value(PARAM_INT, 'User from id'),
901                         'requesteduserid' => new external_value(PARAM_INT, 'User to id'),
902                         'timecreated' => new external_value(PARAM_INT, 'Time created'),
903                     ),
904                     'request record',
905                     VALUE_OPTIONAL
906                 ),
907                 'warnings' => new external_warnings()
908             )
909         );
910     }
912     /**
913      * Confirm a contact request parameters description.
914      *
915      * @return external_function_parameters
916      */
917     public static function confirm_contact_request_parameters() {
918         return new external_function_parameters(
919             [
920                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
921                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
922             ]
923         );
924     }
926     /**
927      * Confirm a contact request.
928      *
929      * @param int $userid The id of the user who is creating the contact request
930      * @param int $requesteduserid The id of the user being requested
931      */
932     public static function confirm_contact_request(int $userid, int $requesteduserid) {
933         global $CFG, $USER;
935         // Check if messaging is enabled.
936         if (empty($CFG->messaging)) {
937             throw new moodle_exception('disabled', 'message');
938         }
940         // Validate context.
941         $context = context_system::instance();
942         self::validate_context($context);
944         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
945         $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
947         $capability = 'moodle/site:manageallmessaging';
948         if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
949             throw new required_capability_exception($context, $capability, 'nopermissions', '');
950         }
952         \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
954         return [];
955     }
957     /**
958      * Confirm a contact request return description.
959      *
960      * @return external_description
961      */
962     public static function confirm_contact_request_returns() {
963         return new external_warnings();
964     }
966     /**
967      * Declines a contact request parameters description.
968      *
969      * @return external_function_parameters
970      */
971     public static function decline_contact_request_parameters() {
972         return new external_function_parameters(
973             [
974                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
975                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
976             ]
977         );
978     }
980     /**
981      * Declines a contact request.
982      *
983      * @param int $userid The id of the user who is creating the contact request
984      * @param int $requesteduserid The id of the user being requested
985      */
986     public static function decline_contact_request(int $userid, int $requesteduserid) {
987         global $CFG, $USER;
989         // Check if messaging is enabled.
990         if (empty($CFG->messaging)) {
991             throw new moodle_exception('disabled', 'message');
992         }
994         // Validate context.
995         $context = context_system::instance();
996         self::validate_context($context);
998         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
999         $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
1001         $capability = 'moodle/site:manageallmessaging';
1002         if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
1003             throw new required_capability_exception($context, $capability, 'nopermissions', '');
1004         }
1006         \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
1008         return [];
1009     }
1011     /**
1012      * Declines a contact request return description.
1013      *
1014      * @return external_description
1015      */
1016     public static function decline_contact_request_returns() {
1017         return new external_warnings();
1018     }
1020     /**
1021      * Return the structure of a message area contact.
1022      *
1023      * @return external_single_structure
1024      * @since Moodle 3.2
1025      */
1026     private static function get_messagearea_contact_structure() {
1027         return new external_single_structure(
1028             array(
1029                 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
1030                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1031                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1032                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1033                 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
1034                 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
1035                 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
1036                 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
1037                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1038                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1039                 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
1040                 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1041                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1042                     VALUE_DEFAULT, null),
1043             )
1044         );
1045     }
1047     /**
1048      * Return the structure of a conversation.
1049      *
1050      * @return external_single_structure
1051      * @since Moodle 3.6
1052      */
1054     private static function get_conversation_structure() {
1055         return new external_single_structure(
1056             array(
1057                 'id' => new external_value(PARAM_INT, 'The conversation id'),
1058                 'name' => new external_value(PARAM_NOTAGS, 'The conversation name, if set', VALUE_DEFAULT, null),
1059                 'subname' => new external_value(PARAM_NOTAGS, 'A subtitle for the conversation name, if set', VALUE_DEFAULT, null),
1060                 'imageurl' => new external_value(PARAM_URL, 'A link to the conversation picture, if set', VALUE_DEFAULT, null),
1061                 'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group)'),
1062                 'membercount' => new external_value(PARAM_INT, 'Total number of conversation members'),
1063                 'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked conversation this conversation as a favourite'),
1064                 'isread' => new external_value(PARAM_BOOL, 'If the user has read all messages in the conversation'),
1065                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1066                     VALUE_DEFAULT, null),
1067                 'members' => new external_multiple_structure(
1068                     self::get_conversation_member_structure(true)
1069                 ),
1070                 'messages' => new external_multiple_structure(
1071                     self::get_conversation_message_structure()
1072                 ),
1073             )
1074         );
1075     }
1077     /**
1078      * Return the structure of a conversation member.
1079      *
1080      * @param bool $includecontactrequests Are we including contact requests?
1081      * @param bool $includeconversations Are we including conversations?
1082      * @return external_single_structure
1083      * @since Moodle 3.6
1084      */
1085     private static function get_conversation_member_structure(bool $includecontactrequests = false,
1086                                                               bool $includeconversations = false) {
1087         $result = [
1088             'id' => new external_value(PARAM_INT, 'The user id'),
1089             'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1090             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1091             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1092             'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1093             'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1094             'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1095             'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
1096             'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
1097             'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
1098             'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
1099         ];
1101         if ($includecontactrequests) {
1102             $result['contactrequests'] = new external_multiple_structure(
1103                 new external_single_structure(
1104                     [
1105                         'id' => new external_value(PARAM_INT, 'The id of the message'),
1106                         'userid' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1107                         'requesteduserid' => new external_value(PARAM_RAW, 'The text of the message'),
1108                         'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1109                     ]
1110                 ), 'The contact requests', VALUE_OPTIONAL
1111             );
1112         }
1114         if ($includeconversations) {
1115             $result['conversations'] = new external_multiple_structure(new external_single_structure(
1116                 array(
1117                     'id' => new external_value(PARAM_INT, 'Conversations id'),
1118                     'type' => new external_value(PARAM_INT, 'Conversation type: private or public'),
1119                     'name' => new external_value(PARAM_TEXT, 'Multilang compatible conversation name'. VALUE_OPTIONAL),
1120                     'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the conversation'),
1121                 ), 'information about conversation', VALUE_OPTIONAL),
1122                 'Conversations between users', VALUE_OPTIONAL
1123             );
1124         }
1126         return new external_single_structure(
1127             $result
1128         );
1129     }
1131     /**
1132      * Return the structure of a message area message.
1133      *
1134      * @return external_single_structure
1135      * @since Moodle 3.6
1136      */
1137     private static function get_conversation_message_structure() {
1138         return new external_single_structure(
1139             array(
1140                 'id' => new external_value(PARAM_INT, 'The id of the message'),
1141                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1142                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1143                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1144             )
1145         );
1146     }
1148     /**
1149      * Return the structure of a message area message.
1150      *
1151      * @return external_single_structure
1152      * @since Moodle 3.2
1153      */
1154     private static function get_messagearea_message_structure() {
1155         return new external_single_structure(
1156             array(
1157                 'id' => new external_value(PARAM_INT, 'The id of the message'),
1158                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1159                 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
1160                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1161                 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
1162                 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
1163                 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
1164                 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
1165                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1166                 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
1167             )
1168         );
1169     }
1171     /**
1172      * Get messagearea search users in course parameters.
1173      *
1174      * @deprecated since 3.6
1175      *
1176      * @return external_function_parameters
1177      * @since 3.2
1178      */
1179     public static function data_for_messagearea_search_users_in_course_parameters() {
1180         return new external_function_parameters(
1181             array(
1182                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1183                 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
1184                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1185                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1186                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1187             )
1188         );
1189     }
1191     /**
1192      * Get messagearea search users in course results.
1193      *
1194      * @deprecated since 3.6
1195      *
1196      * NOTE: We are deprecating this function but not search_users_in_course API function for backwards compatibility
1197      * with messaging UI. But should be removed once new group messaging UI is in place and old messaging UI is removed.
1198      * Followup: MDL-63915
1199      *
1200      * @param int $userid The id of the user who is performing the search
1201      * @param int $courseid The id of the course
1202      * @param string $search The string being searched
1203      * @param int $limitfrom
1204      * @param int $limitnum
1205      * @return stdClass
1206      * @throws moodle_exception
1207      * @since 3.2
1208      */
1209     public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
1210                                                                        $limitnum = 0) {
1211         global $CFG, $PAGE, $USER;
1213         // Check if messaging is enabled.
1214         if (empty($CFG->messaging)) {
1215             throw new moodle_exception('disabled', 'message');
1216         }
1218         $systemcontext = context_system::instance();
1220         $params = array(
1221             'userid' => $userid,
1222             'courseid' => $courseid,
1223             'search' => $search,
1224             'limitfrom' => $limitfrom,
1225             'limitnum' => $limitnum
1226         );
1227         $params = self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
1228         self::validate_context($systemcontext);
1230         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1231             throw new moodle_exception('You do not have permission to perform this action.');
1232         }
1234         $users = \core_message\api::search_users_in_course(
1235             $params['userid'],
1236             $params['courseid'],
1237             $params['search'],
1238             $params['limitfrom'],
1239             $params['limitnum']
1240         );
1241         $results = new \core_message\output\messagearea\user_search_results($users);
1243         $renderer = $PAGE->get_renderer('core_message');
1244         return $results->export_for_template($renderer);
1245     }
1247     /**
1248      * Get messagearea search users in course returns.
1249      *
1250      * @deprecated since 3.6
1251      *
1252      * @return external_single_structure
1253      * @since 3.2
1254      */
1255     public static function data_for_messagearea_search_users_in_course_returns() {
1256         return new external_single_structure(
1257             array(
1258                 'contacts' => new external_multiple_structure(
1259                     self::get_messagearea_contact_structure()
1260                 ),
1261             )
1262         );
1263     }
1265     /**
1266      * Marking the method as deprecated.
1267      *
1268      * @return bool
1269      */
1270     public static function data_for_messagearea_search_users_in_course_is_deprecated() {
1271         return true;
1272     }
1274     /**
1275      * Get messagearea search users parameters.
1276      *
1277      * @deprecated since 3.6
1278      *
1279      * @return external_function_parameters
1280      * @since 3.2
1281      */
1282     public static function data_for_messagearea_search_users_parameters() {
1283         return new external_function_parameters(
1284             array(
1285                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1286                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1287                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1288             )
1289         );
1290     }
1292     /**
1293      * Get messagearea search users results.
1294      *
1295      * @deprecated since 3.6
1296      *
1297      * NOTE: We are deprecating this function but not search_users API function for backwards compatibility
1298      * with messaging UI. But should be removed once new group messaging UI is in place and old messaging UI is removed.
1299      * Followup: MDL-63915
1300      *
1301      * @param int $userid The id of the user who is performing the search
1302      * @param string $search The string being searched
1303      * @param int $limitnum
1304      * @return stdClass
1305      * @throws moodle_exception
1306      * @since 3.2
1307      */
1308     public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1309         global $CFG, $PAGE, $USER;
1311         // Check if messaging is enabled.
1312         if (empty($CFG->messaging)) {
1313             throw new moodle_exception('disabled', 'message');
1314         }
1316         $systemcontext = context_system::instance();
1318         $params = array(
1319             'userid' => $userid,
1320             'search' => $search,
1321             'limitnum' => $limitnum
1322         );
1323         $params = self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1324         self::validate_context($systemcontext);
1326         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1327             throw new moodle_exception('You do not have permission to perform this action.');
1328         }
1330         list($contacts, $courses, $noncontacts) = \core_message\api::search_users(
1331             $params['userid'],
1332             $params['search'],
1333             $params['limitnum']
1334         );
1336         $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1338         $renderer = $PAGE->get_renderer('core_message');
1339         return $search->export_for_template($renderer);
1340     }
1342     /**
1343      * Get messagearea search users returns.
1344      *
1345      * @deprecated since 3.6
1346      *
1347      * @return external_single_structure
1348      * @since 3.2
1349      */
1350     public static function data_for_messagearea_search_users_returns() {
1351         return new external_single_structure(
1352             array(
1353                 'contacts' => new external_multiple_structure(
1354                     self::get_messagearea_contact_structure()
1355                 ),
1356                 'courses' => new external_multiple_structure(
1357                     new external_single_structure(
1358                         array(
1359                             'id' => new external_value(PARAM_INT, 'The course id'),
1360                             'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1361                             'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1362                         )
1363                     )
1364                 ),
1365                 'noncontacts' => new external_multiple_structure(
1366                     self::get_messagearea_contact_structure()
1367                 )
1368             )
1369         );
1370     }
1372     /**
1373      * Marking the method as deprecated.
1374      *
1375      * @return bool
1376      */
1377     public static function data_for_messagearea_search_users_is_deprecated() {
1378         return true;
1379     }
1381     /**
1382      * Get messagearea message search users parameters.
1383      *
1384      * @return external_function_parameters
1385      * @since 3.6
1386      */
1387     public static function message_search_users_parameters() {
1388         return new external_function_parameters(
1389             array(
1390                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1391                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1392                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1393                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1394             )
1395         );
1396     }
1398     /**
1399      * Get search users results.
1400      *
1401      * @param int $userid The id of the user who is performing the search
1402      * @param string $search The string being searched
1403      * @param int $limitfrom
1404      * @param int $limitnum
1405      * @return array
1406      * @throws moodle_exception
1407      * @since 3.6
1408      */
1409     public static function message_search_users($userid, $search, $limitfrom = 0, $limitnum = 0) {
1410         global $USER;
1412         $systemcontext = context_system::instance();
1414         $params = array(
1415             'userid' => $userid,
1416             'search' => $search,
1417             'limitfrom' => $limitfrom,
1418             'limitnum' => $limitnum
1419         );
1420         $params = self::validate_parameters(self::message_search_users_parameters(), $params);
1421         self::validate_context($systemcontext);
1423         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1424             throw new moodle_exception('You do not have permission to perform this action.');
1425         }
1427         list($contacts, $noncontacts) = \core_message\api::message_search_users(
1428             $params['userid'],
1429             $params['search'],
1430             $params['limitfrom'],
1431             $params['limitnum']);
1433         return array('contacts' => $contacts, 'noncontacts' => $noncontacts);
1434     }
1436     /**
1437      * Get messagearea message search users returns.
1438      *
1439      * @return external_single_structure
1440      * @since 3.2
1441      */
1442     public static function message_search_users_returns() {
1443         return new external_single_structure(
1444             array(
1445                 'contacts' => new external_multiple_structure(
1446                     self::get_conversation_member_structure(false, true)
1447                 ),
1448                 'noncontacts' => new external_multiple_structure(
1449                     self::get_conversation_member_structure(false, true)
1450                 )
1451             )
1452         );
1453     }
1455     /**
1456      * Get messagearea search messages parameters.
1457      *
1458      * @return external_function_parameters
1459      * @since 3.2
1460      */
1461     public static function data_for_messagearea_search_messages_parameters() {
1462         return new external_function_parameters(
1463             array(
1464                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1465                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1466                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1467                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1468             )
1469         );
1470     }
1472     /**
1473      * Get messagearea search messages results.
1474      *
1475      * @param int $userid The id of the user who is performing the search
1476      * @param string $search The string being searched
1477      * @param int $limitfrom
1478      * @param int $limitnum
1479      * @return stdClass
1480      * @throws moodle_exception
1481      * @since 3.2
1482      */
1483     public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1484         global $CFG, $PAGE, $USER;
1486         // Check if messaging is enabled.
1487         if (empty($CFG->messaging)) {
1488             throw new moodle_exception('disabled', 'message');
1489         }
1491         $systemcontext = context_system::instance();
1493         $params = array(
1494             'userid' => $userid,
1495             'search' => $search,
1496             'limitfrom' => $limitfrom,
1497             'limitnum' => $limitnum
1499         );
1500         $params = self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1501         self::validate_context($systemcontext);
1503         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1504             throw new moodle_exception('You do not have permission to perform this action.');
1505         }
1507         $messages = \core_message\api::search_messages(
1508             $params['userid'],
1509             $params['search'],
1510             $params['limitfrom'],
1511             $params['limitnum']
1512         );
1513         $results = new \core_message\output\messagearea\message_search_results($messages);
1515         $renderer = $PAGE->get_renderer('core_message');
1516         return $results->export_for_template($renderer);
1517     }
1519     /**
1520      * Get messagearea search messages returns.
1521      *
1522      * @return external_single_structure
1523      * @since 3.2
1524      */
1525     public static function data_for_messagearea_search_messages_returns() {
1526         return new external_single_structure(
1527             array(
1528                 'contacts' => new external_multiple_structure(
1529                     self::get_messagearea_contact_structure()
1530                 )
1531             )
1532         );
1533     }
1535     /**
1536      * Get conversations parameters.
1537      *
1538      * @return external_function_parameters
1539      * @since 3.6
1540      */
1541     public static function get_conversations_parameters() {
1542         return new external_function_parameters(
1543             array(
1544                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1545                 'limitfrom' => new external_value(PARAM_INT, 'The offset to start at', VALUE_DEFAULT, 0),
1546                 'limitnum' => new external_value(PARAM_INT, 'Limit number of conversations to this', VALUE_DEFAULT, 0),
1547                 'type' => new external_value(PARAM_INT, 'Filter by type', VALUE_DEFAULT, null),
1548                 'favourites' => new external_value(PARAM_BOOL, 'Whether to restrict the results to contain NO favourite
1549                 conversations (false), ONLY favourite conversation (true), or ignore any restriction altogether (null)',
1550                     VALUE_DEFAULT, null),
1552             )
1553         );
1554     }
1556     /**
1557      * Get the list of conversations for the user.
1558      *
1559      * @param int $userid The id of the user who is performing the search
1560      * @param int $limitfrom
1561      * @param int $limitnum
1562      * @param int|null $type
1563      * @param bool|null $favourites
1564      * @return stdClass
1565      * @throws \moodle_exception if the messaging feature is disabled on the site.
1566      * @since 3.2
1567      */
1568     public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null) {
1569         global $CFG, $USER;
1571         // All the standard BL checks.
1572         if (empty($CFG->messaging)) {
1573             throw new moodle_exception('disabled', 'message');
1574         }
1576         $params = array(
1577             'userid' => $userid,
1578             'limitfrom' => $limitfrom,
1579             'limitnum' => $limitnum,
1580             'type' => $type,
1581             'favourites' => $favourites
1582         );
1583         $params = self::validate_parameters(self::get_conversations_parameters(), $params);
1585         $systemcontext = context_system::instance();
1586         self::validate_context($systemcontext);
1588         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1589             throw new moodle_exception('You do not have permission to perform this action.');
1590         }
1592         $conversations = \core_message\api::get_conversations(
1593             $params['userid'],
1594             $params['limitfrom'],
1595             $params['limitnum'],
1596             $params['type'],
1597             $params['favourites']
1598         );
1600         return (object) ['conversations' => $conversations];
1601     }
1603     /**
1604      * Get conversations returns.
1605      *
1606      * @return external_single_structure
1607      * @since 3.6
1608      */
1609     public static function get_conversations_returns() {
1610         return new external_single_structure(
1611             [
1612                 'conversations' => new external_multiple_structure(
1613                     self::get_conversation_structure()
1614                 )
1615             ]
1616         );
1617     }
1619     /**
1620      * The messagearea conversations parameters.
1621      *
1622      * @deprecated since 3.6
1623      * @return external_function_parameters
1624      * @since 3.2
1625      */
1626     public static function data_for_messagearea_conversations_parameters() {
1627         return new external_function_parameters(
1628             array(
1629                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1630                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1631                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1632             )
1633         );
1634     }
1636     /**
1637      * Get messagearea conversations.
1638      *
1639      * NOTE FOR FINAL DEPRECATION:
1640      * When removing this method, please also consider removal of get_conversations_legacy_formatter()
1641      * from the \core_message\helper class. This helper method was used solely to format the new get_conversations() return data
1642      * into the old format used here, and in message/index.php. If we no longer need either of these, then that method can be
1643      * removed.
1644      *
1645      * @deprecated since 3.6
1646      * @param int $userid The id of the user who we are viewing conversations for
1647      * @param int $limitfrom
1648      * @param int $limitnum
1649      * @return stdClass
1650      * @throws moodle_exception
1651      * @since 3.2
1652      */
1653     public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1654         global $CFG, $PAGE, $USER;
1656         // Check if messaging is enabled.
1657         if (empty($CFG->messaging)) {
1658             throw new moodle_exception('disabled', 'message');
1659         }
1661         $systemcontext = context_system::instance();
1663         $params = array(
1664             'userid' => $userid,
1665             'limitfrom' => $limitfrom,
1666             'limitnum' => $limitnum
1667         );
1668         $params = self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1669         self::validate_context($systemcontext);
1671         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1672             throw new moodle_exception('You do not have permission to perform this action.');
1673         }
1675         $conversations = \core_message\api::get_conversations($params['userid'], $params['limitfrom'], $params['limitnum']);
1677         // Format the conversations in the legacy style, as the get_conversations method has since been changed.
1678         $conversations = \core_message\helper::get_conversations_legacy_formatter($conversations);
1680         $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1682         $renderer = $PAGE->get_renderer('core_message');
1683         return $conversations->export_for_template($renderer);
1684     }
1686     /**
1687      * The messagearea conversations return structure.
1688      *
1689      * @deprecated since 3.6
1690      * @return external_single_structure
1691      * @since 3.2
1692      */
1693     public static function data_for_messagearea_conversations_returns() {
1694         return new external_single_structure(
1695             array(
1696                 'contacts' => new external_multiple_structure(
1697                     self::get_messagearea_contact_structure()
1698                 )
1699             )
1700         );
1701     }
1703     /**
1704      * Marking the method as deprecated.
1705      *
1706      * @return bool
1707      */
1708     public static function data_for_messagearea_conversations_is_deprecated() {
1709         return true;
1710     }
1712     /**
1713      * The messagearea contacts return parameters.
1714      *
1715      * @deprecated since 3.6
1716      * @return external_function_parameters
1717      * @since 3.2
1718      */
1719     public static function data_for_messagearea_contacts_parameters() {
1720         return self::data_for_messagearea_conversations_parameters();
1721     }
1723     /**
1724      * Get messagearea contacts parameters.
1725      *
1726      * @deprecated since 3.6
1727      * @param int $userid The id of the user who we are viewing conversations for
1728      * @param int $limitfrom
1729      * @param int $limitnum
1730      * @return stdClass
1731      * @throws moodle_exception
1732      * @since 3.2
1733      */
1734     public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1735         global $CFG, $PAGE, $USER;
1737         // Check if messaging is enabled.
1738         if (empty($CFG->messaging)) {
1739             throw new moodle_exception('disabled', 'message');
1740         }
1742         $systemcontext = context_system::instance();
1744         $params = array(
1745             'userid' => $userid,
1746             'limitfrom' => $limitfrom,
1747             'limitnum' => $limitnum
1748         );
1749         $params = self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1750         self::validate_context($systemcontext);
1752         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1753             throw new moodle_exception('You do not have permission to perform this action.');
1754         }
1756         $contacts = \core_message\api::get_contacts($params['userid'], $params['limitfrom'], $params['limitnum']);
1757         $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1759         $renderer = $PAGE->get_renderer('core_message');
1760         return $contacts->export_for_template($renderer);
1761     }
1763     /**
1764      * The messagearea contacts return structure.
1765      *
1766      * @deprecated since 3.6
1767      * @return external_single_structure
1768      * @since 3.2
1769      */
1770     public static function data_for_messagearea_contacts_returns() {
1771         return self::data_for_messagearea_conversations_returns();
1772     }
1774     /**
1775      * Marking the method as deprecated.
1776      *
1777      * @return bool
1778      */
1779     public static function data_for_messagearea_contacts_is_deprecated() {
1780         return true;
1781     }
1783     /**
1784      * The messagearea messages parameters.
1785      *
1786      * @deprecated since 3.6
1787      * @return external_function_parameters
1788      * @since 3.2
1789      */
1790     public static function data_for_messagearea_messages_parameters() {
1791         return new external_function_parameters(
1792             array(
1793                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1794                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1795                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1796                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1797                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1798                 'timefrom' => new external_value(PARAM_INT,
1799                     'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1800             )
1801         );
1802     }
1804     /**
1805      * Get messagearea messages.
1806      *
1807      * @deprecated since 3.6
1808      * @param int $currentuserid The current user's id
1809      * @param int $otheruserid The other user's id
1810      * @param int $limitfrom
1811      * @param int $limitnum
1812      * @param boolean $newest
1813      * @return stdClass
1814      * @throws moodle_exception
1815      * @since 3.2
1816      */
1817     public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
1818                                                          $newest = false, $timefrom = 0) {
1819         global $CFG, $PAGE, $USER;
1821         // Check if messaging is enabled.
1822         if (empty($CFG->messaging)) {
1823             throw new moodle_exception('disabled', 'message');
1824         }
1826         $systemcontext = context_system::instance();
1828         $params = array(
1829             'currentuserid' => $currentuserid,
1830             'otheruserid' => $otheruserid,
1831             'limitfrom' => $limitfrom,
1832             'limitnum' => $limitnum,
1833             'newest' => $newest,
1834             'timefrom' => $timefrom,
1835         );
1836         $params = self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
1837         self::validate_context($systemcontext);
1839         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1840             throw new moodle_exception('You do not have permission to perform this action.');
1841         }
1843         if ($params['newest']) {
1844             $sort = 'timecreated DESC';
1845         } else {
1846             $sort = 'timecreated ASC';
1847         }
1849         // We need to enforce a one second delay on messages to avoid race conditions of current
1850         // messages still being sent.
1851         //
1852         // There is a chance that we could request messages before the current time's
1853         // second has elapsed and while other messages are being sent in that same second. In which
1854         // case those messages will be lost.
1855         //
1856         // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1857         if (!empty($params['timefrom'])) {
1858             $timeto = time() - 1;
1859         } else {
1860             $timeto = 0;
1861         }
1863         // No requesting messages from the current time, as stated above.
1864         if ($params['timefrom'] == time()) {
1865             $messages = [];
1866         } else {
1867             $messages = \core_message\api::get_messages($params['currentuserid'], $params['otheruserid'], $params['limitfrom'],
1868                                                         $params['limitnum'], $sort, $params['timefrom'], $timeto);
1869         }
1871         $messages = new \core_message\output\messagearea\messages($params['currentuserid'], $params['otheruserid'], $messages);
1873         $renderer = $PAGE->get_renderer('core_message');
1874         return $messages->export_for_template($renderer);
1875     }
1877     /**
1878      * The messagearea messages return structure.
1879      *
1880      * @deprecated since 3.6
1881      * @return external_single_structure
1882      * @since 3.2
1883      */
1884     public static function data_for_messagearea_messages_returns() {
1885         return new external_single_structure(
1886             array(
1887                 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
1888                     the messages on behalf of?'),
1889                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1890                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1891                 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
1892                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1893                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1894                 'messages' => new external_multiple_structure(
1895                     self::get_messagearea_message_structure()
1896                 ),
1897                 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
1898             )
1899         );
1900     }
1902     /**
1903      * Marking the method as deprecated.
1904      *
1905      * @return bool
1906      */
1907     public static function data_for_messagearea_messages_is_deprecated() {
1908         return true;
1909     }
1911     /**
1912      * The conversation messages parameters.
1913      *
1914      * @return external_function_parameters
1915      * @since 3.6
1916      */
1917     public static function get_conversation_messages_parameters() {
1918         return new external_function_parameters(
1919             array(
1920                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1921                 'convid' => new external_value(PARAM_INT, 'The conversation id'),
1922                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1923                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1924                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1925                 'timefrom' => new external_value(PARAM_INT,
1926                     'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1927             )
1928         );
1929     }
1931     /**
1932      * Get conversation messages.
1933      *
1934      * @param  int $currentuserid The current user's id.
1935      * @param  int $convid The conversation id.
1936      * @param  int $limitfrom Return a subset of records, starting at this point (optional).
1937      * @param  int $limitnum Return a subset comprising this many records in total (optional, required if $limitfrom is set).
1938      * @param  bool $newest True for getting first newest messages, false otherwise.
1939      * @param  int  $timefrom The time from the conversation messages to get.
1940      * @return stdClass The messages and members who have sent some of these messages.
1941      * @throws moodle_exception
1942      * @since 3.6
1943      */
1944     public static function get_conversation_messages(int $currentuserid, int $convid, int $limitfrom = 0, int $limitnum = 0,
1945                                                          bool $newest = false, int $timefrom = 0) {
1946         global $CFG, $PAGE, $USER;
1948         // Check if messaging is enabled.
1949         if (empty($CFG->messaging)) {
1950             throw new moodle_exception('disabled', 'message');
1951         }
1953         $systemcontext = context_system::instance();
1955         $params = array(
1956             'currentuserid' => $currentuserid,
1957             'convid' => $convid,
1958             'limitfrom' => $limitfrom,
1959             'limitnum' => $limitnum,
1960             'newest' => $newest,
1961             'timefrom' => $timefrom,
1962         );
1963         $params = self::validate_parameters(self::get_conversation_messages_parameters(), $params);
1964         self::validate_context($systemcontext);
1966         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1967             throw new moodle_exception('You do not have permission to perform this action.');
1968         }
1970         $sort = $newest ? 'timecreated DESC' : 'timecreated ASC';
1972         // We need to enforce a one second delay on messages to avoid race conditions of current
1973         // messages still being sent.
1974         //
1975         // There is a chance that we could request messages before the current time's
1976         // second has elapsed and while other messages are being sent in that same second. In which
1977         // case those messages will be lost.
1978         //
1979         // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1980         $timeto = empty($params['timefrom']) ? 0 : time() - 1;
1982         // No requesting messages from the current time, as stated above.
1983         if ($params['timefrom'] == time()) {
1984             $messages = [];
1985         } else {
1986             $messages = \core_message\api::get_conversation_messages(
1987                 $params['currentuserid'],
1988                 $params['convid'],
1989                 $params['limitfrom'],
1990                 $params['limitnum'],
1991                 $sort,
1992                 $params['timefrom'],
1993                 $timeto);
1994         }
1996         return $messages;
1997     }
1999     /**
2000      * The messagearea messages return structure.
2001      *
2002      * @return external_single_structure
2003      * @since 3.6
2004      */
2005     public static function get_conversation_messages_returns() {
2006         return new external_single_structure(
2007             array(
2008                 'id' => new external_value(PARAM_INT, 'The conversation id'),
2009                 'members' => new external_multiple_structure(
2010                     self::get_conversation_member_structure()
2011                 ),
2012                 'messages' => new external_multiple_structure(
2013                     self::get_conversation_message_structure()
2014                 ),
2015             )
2016         );
2017     }
2019     /**
2020      * The get most recent message return parameters.
2021      *
2022      * @deprecated since 3.6
2023      * @return external_function_parameters
2024      * @since 3.2
2025      */
2026     public static function data_for_messagearea_get_most_recent_message_parameters() {
2027         return new external_function_parameters(
2028             array(
2029                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2030                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2031             )
2032         );
2033     }
2035     /**
2036      * Get the most recent message in a conversation.
2037      *
2038      * @deprecated since 3.6
2039      * @param int $currentuserid The current user's id
2040      * @param int $otheruserid The other user's id
2041      * @return stdClass
2042      * @throws moodle_exception
2043      * @since 3.2
2044      */
2045     public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
2046         global $CFG, $PAGE, $USER;
2048         // Check if messaging is enabled.
2049         if (empty($CFG->messaging)) {
2050             throw new moodle_exception('disabled', 'message');
2051         }
2053         $systemcontext = context_system::instance();
2055         $params = array(
2056             'currentuserid' => $currentuserid,
2057             'otheruserid' => $otheruserid
2058         );
2059         $params = self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
2060         self::validate_context($systemcontext);
2062         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2063             throw new moodle_exception('You do not have permission to perform this action.');
2064         }
2066         $message = \core_message\api::get_most_recent_message($params['currentuserid'], $params['otheruserid']);
2067         $message = new \core_message\output\messagearea\message($message);
2069         $renderer = $PAGE->get_renderer('core_message');
2070         return $message->export_for_template($renderer);
2071     }
2073     /**
2074      * The get most recent message return structure.
2075      *
2076      * @deprecated since 3.6
2077      * @return external_single_structure
2078      * @since 3.2
2079      */
2080     public static function data_for_messagearea_get_most_recent_message_returns() {
2081         return self::get_messagearea_message_structure();
2082     }
2084     /**
2085      * Marking the method as deprecated.
2086      *
2087      * @return bool
2088      */
2089     public static function data_for_messagearea_get_most_recent_message_is_deprecated() {
2090         return true;
2091     }
2093     /**
2094      * The get profile parameters.
2095      *
2096      * @deprecated since 3.6
2097      * @return external_function_parameters
2098      * @since 3.2
2099      */
2100     public static function data_for_messagearea_get_profile_parameters() {
2101         return new external_function_parameters(
2102             array(
2103                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2104                 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
2105             )
2106         );
2107     }
2109     /**
2110      * Get the profile information for a contact.
2111      *
2112      * @deprecated since 3.6
2113      * @param int $currentuserid The current user's id
2114      * @param int $otheruserid The id of the user whose profile we are viewing
2115      * @return stdClass
2116      * @throws moodle_exception
2117      * @since 3.2
2118      */
2119     public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
2120         global $CFG, $PAGE, $USER;
2122         // Check if messaging is enabled.
2123         if (empty($CFG->messaging)) {
2124             throw new moodle_exception('disabled', 'message');
2125         }
2127         $systemcontext = context_system::instance();
2129         $params = array(
2130             'currentuserid' => $currentuserid,
2131             'otheruserid' => $otheruserid
2132         );
2133         $params = self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
2134         self::validate_context($systemcontext);
2136         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2137             throw new moodle_exception('You do not have permission to perform this action.');
2138         }
2140         $profile = \core_message\api::get_profile($params['currentuserid'], $params['otheruserid']);
2141         $profile = new \core_message\output\messagearea\profile($profile);
2143         $renderer = $PAGE->get_renderer('core_message');
2144         return $profile->export_for_template($renderer);
2145     }
2147     /**
2148      * The get profile return structure.
2149      *
2150      * @deprecated since 3.6
2151      * @return external_single_structure
2152      * @since 3.2
2153      */
2154     public static function data_for_messagearea_get_profile_returns() {
2155         return new external_single_structure(
2156             array(
2157                 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
2158                 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
2159                 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
2160                 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
2161                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
2162                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
2163                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
2164                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2165                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2166                 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
2167                 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
2168             )
2169         );
2170     }
2172     /**
2173      * Marking the method as deprecated.
2174      *
2175      * @return bool
2176      */
2177     public static function data_for_messagearea_get_profile_is_deprecated() {
2178         return true;
2179     }
2181     /**
2182      * Get contacts parameters description.
2183      *
2184      * @return external_function_parameters
2185      * @since Moodle 2.5
2186      */
2187     public static function get_contacts_parameters() {
2188         return new external_function_parameters(array());
2189     }
2191     /**
2192      * Get contacts.
2193      *
2194      * @return external_description
2195      * @since Moodle 2.5
2196      */
2197     public static function get_contacts() {
2198         global $CFG, $PAGE, $USER;
2200         // Check if messaging is enabled.
2201         if (empty($CFG->messaging)) {
2202             throw new moodle_exception('disabled', 'message');
2203         }
2205         require_once($CFG->dirroot . '/user/lib.php');
2207         $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
2208         $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
2209         foreach ($contacts as $contact) {
2210             // Set the mode.
2211             $mode = 'offline';
2212             if (\core_message\helper::is_online($contact->lastaccess)) {
2213                 $mode = 'online';
2214             }
2216             $newcontact = array(
2217                 'id' => $contact->id,
2218                 'fullname' => fullname($contact),
2219                 'unread' => $contact->messagecount
2220             );
2222             $userpicture = new user_picture($contact);
2223             $userpicture->size = 1; // Size f1.
2224             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2225             $userpicture->size = 0; // Size f2.
2226             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2228             $allcontacts[$mode][$contact->id] = $newcontact;
2229         }
2231         $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
2232         foreach ($strangers as $contact) {
2233             $newcontact = array(
2234                 'id' => $contact->id,
2235                 'fullname' => fullname($contact),
2236                 'unread' => $contact->messagecount
2237             );
2239             $userpicture = new user_picture($contact);
2240             $userpicture->size = 1; // Size f1.
2241             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2242             $userpicture->size = 0; // Size f2.
2243             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2245             $allcontacts['strangers'][$contact->id] = $newcontact;
2246         }
2248         // Add noreply user and support user to the list, if they don't exist.
2249         $supportuser = core_user::get_support_user();
2250         if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
2251             $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
2252             if ($supportuser->messagecount > 0) {
2253                 $supportuser->fullname = fullname($supportuser);
2254                 $supportuser->unread = $supportuser->messagecount;
2255                 $allcontacts['strangers'][$supportuser->id] = $supportuser;
2256             }
2257         }
2259         $noreplyuser = core_user::get_noreply_user();
2260         if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
2261             $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
2262             if ($noreplyuser->messagecount > 0) {
2263                 $noreplyuser->fullname = fullname($noreplyuser);
2264                 $noreplyuser->unread = $noreplyuser->messagecount;
2265                 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
2266             }
2267         }
2269         return $allcontacts;
2270     }
2272     /**
2273      * Get contacts return description.
2274      *
2275      * @return external_description
2276      * @since Moodle 2.5
2277      */
2278     public static function get_contacts_returns() {
2279         return new external_single_structure(
2280             array(
2281                 'online' => new external_multiple_structure(
2282                     new external_single_structure(
2283                         array(
2284                             'id' => new external_value(PARAM_INT, 'User ID'),
2285                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2286                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2287                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2288                             'unread' => new external_value(PARAM_INT, 'Unread message count')
2289                         )
2290                     ),
2291                     'List of online contacts'
2292                 ),
2293                 'offline' => new external_multiple_structure(
2294                     new external_single_structure(
2295                         array(
2296                             'id' => new external_value(PARAM_INT, 'User ID'),
2297                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2298                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2299                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2300                             'unread' => new external_value(PARAM_INT, 'Unread message count')
2301                         )
2302                     ),
2303                     'List of offline contacts'
2304                 ),
2305                 'strangers' => new external_multiple_structure(
2306                     new external_single_structure(
2307                         array(
2308                             'id' => new external_value(PARAM_INT, 'User ID'),
2309                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2310                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2311                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2312                             'unread' => new external_value(PARAM_INT, 'Unread message count')
2313                         )
2314                     ),
2315                     'List of users that are not in the user\'s contact list but have sent a message'
2316                 )
2317             )
2318         );
2319     }
2321     /**
2322      * Search contacts parameters description.
2323      *
2324      * @return external_function_parameters
2325      * @since Moodle 2.5
2326      */
2327     public static function search_contacts_parameters() {
2328         return new external_function_parameters(
2329             array(
2330                 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
2331                 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
2332                     VALUE_DEFAULT, false)
2333             )
2334         );
2335     }
2337     /**
2338      * Search contacts.
2339      *
2340      * @param string $searchtext query string.
2341      * @param bool $onlymycourses limit the search to the user's courses only.
2342      * @return external_description
2343      * @since Moodle 2.5
2344      */
2345     public static function search_contacts($searchtext, $onlymycourses = false) {
2346         global $CFG, $USER, $PAGE;
2347         require_once($CFG->dirroot . '/user/lib.php');
2349         // Check if messaging is enabled.
2350         if (empty($CFG->messaging)) {
2351             throw new moodle_exception('disabled', 'message');
2352         }
2354         require_once($CFG->libdir . '/enrollib.php');
2356         $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
2357         $params = self::validate_parameters(self::search_contacts_parameters(), $params);
2359         // Extra validation, we do not allow empty queries.
2360         if ($params['searchtext'] === '') {
2361             throw new moodle_exception('querystringcannotbeempty');
2362         }
2364         $courseids = array();
2365         if ($params['onlymycourses']) {
2366             $mycourses = enrol_get_my_courses(array('id'));
2367             foreach ($mycourses as $mycourse) {
2368                 $courseids[] = $mycourse->id;
2369             }
2370         } else {
2371             $courseids[] = SITEID;
2372         }
2374         // Retrieving the users matching the query.
2375         $users = message_search_users($courseids, $params['searchtext']);
2376         $results = array();
2377         foreach ($users as $user) {
2378             $results[$user->id] = $user;
2379         }
2381         // Reorganising information.
2382         foreach ($results as &$user) {
2383             $newuser = array(
2384                 'id' => $user->id,
2385                 'fullname' => fullname($user)
2386             );
2388             // Avoid undefined property notice as phone not specified.
2389             $user->phone1 = null;
2390             $user->phone2 = null;
2392             $userpicture = new user_picture($user);
2393             $userpicture->size = 1; // Size f1.
2394             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2395             $userpicture->size = 0; // Size f2.
2396             $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2398             $user = $newuser;
2399         }
2401         return $results;
2402     }
2404     /**
2405      * Search contacts return description.
2406      *
2407      * @return external_description
2408      * @since Moodle 2.5
2409      */
2410     public static function search_contacts_returns() {
2411         return new external_multiple_structure(
2412             new external_single_structure(
2413                 array(
2414                     'id' => new external_value(PARAM_INT, 'User ID'),
2415                     'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2416                     'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2417                     'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
2418                 )
2419             ),
2420             'List of contacts'
2421         );
2422     }
2424     /**
2425      * Get messages parameters description.
2426      *
2427      * @return external_function_parameters
2428      * @since 2.8
2429      */
2430     public static function get_messages_parameters() {
2431         return new external_function_parameters(
2432             array(
2433                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2434                 'useridfrom' => new external_value(
2435                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2436                     VALUE_DEFAULT, 0),
2437                 'type' => new external_value(
2438                     PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
2439                     VALUE_DEFAULT, 'both'),
2440                 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
2441                 'newestfirst' => new external_value(
2442                     PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
2443                     VALUE_DEFAULT, true),
2444                 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
2445                 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
2446             )
2447         );
2448     }
2450     /**
2451      * Get messages function implementation.
2452      *
2453      * @since  2.8
2454      * @throws invalid_parameter_exception
2455      * @throws moodle_exception
2456      * @param  int      $useridto       the user id who received the message
2457      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
2458      * @param  string   $type           type of message to return, expected values: notifications, conversations and both
2459      * @param  bool     $read           true for retreiving read messages, false for unread
2460      * @param  bool     $newestfirst    true for ordering by newest first, false for oldest first
2461      * @param  int      $limitfrom      limit from
2462      * @param  int      $limitnum       limit num
2463      * @return external_description
2464      */
2465     public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
2466                                         $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
2467         global $CFG, $USER;
2469         $warnings = array();
2471         $params = array(
2472             'useridto' => $useridto,
2473             'useridfrom' => $useridfrom,
2474             'type' => $type,
2475             'read' => $read,
2476             'newestfirst' => $newestfirst,
2477             'limitfrom' => $limitfrom,
2478             'limitnum' => $limitnum
2479         );
2481         $params = self::validate_parameters(self::get_messages_parameters(), $params);
2483         $context = context_system::instance();
2484         self::validate_context($context);
2486         $useridto = $params['useridto'];
2487         $useridfrom = $params['useridfrom'];
2488         $type = $params['type'];
2489         $read = $params['read'];
2490         $newestfirst = $params['newestfirst'];
2491         $limitfrom = $params['limitfrom'];
2492         $limitnum = $params['limitnum'];
2494         $allowedvalues = array('notifications', 'conversations', 'both');
2495         if (!in_array($type, $allowedvalues)) {
2496             throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
2497                 'allowed values are: ' . implode(',', $allowedvalues));
2498         }
2500         // Check if private messaging between users is allowed.
2501         if (empty($CFG->messaging)) {
2502             // If we are retreiving only conversations, and messaging is disabled, throw an exception.
2503             if ($type == "conversations") {
2504                 throw new moodle_exception('disabled', 'message');
2505             }
2506             if ($type == "both") {
2507                 $warning = array();
2508                 $warning['item'] = 'message';
2509                 $warning['itemid'] = $USER->id;
2510                 $warning['warningcode'] = '1';
2511                 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
2512                     Only notifications will be returned';
2513                 $warnings[] = $warning;
2514             }
2515         }
2517         if (!empty($useridto)) {
2518             if (core_user::is_real_user($useridto)) {
2519                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2520             } else {
2521                 throw new moodle_exception('invaliduser');
2522             }
2523         }
2525         if (!empty($useridfrom)) {
2526             // We use get_user here because the from user can be the noreply or support user.
2527             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2528         }
2530         // Check if the current user is the sender/receiver or just a privileged user.
2531         if ($useridto != $USER->id and $useridfrom != $USER->id and
2532              !has_capability('moodle/site:readallmessages', $context)) {
2533             throw new moodle_exception('accessdenied', 'admin');
2534         }
2536         // Which type of messages to retrieve.
2537         $notifications = -1;
2538         if ($type != 'both') {
2539             $notifications = ($type == 'notifications') ? 1 : 0;
2540         }
2542         $orderdirection = $newestfirst ? 'DESC' : 'ASC';
2543         $sort = "mr.timecreated $orderdirection";
2545         if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
2546             $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
2548             // In some cases, we don't need to get the to/from user objects from the sql query.
2549             $userfromfullname = '';
2550             $usertofullname = '';
2552             // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
2553             if (!empty($useridto)) {
2554                 $usertofullname = fullname($userto, $canviewfullname);
2555                 // The user from may or may not be filled.
2556                 if (!empty($useridfrom)) {
2557                     $userfromfullname = fullname($userfrom, $canviewfullname);
2558                 }
2559             } else {
2560                 // If the useridto field is empty, the useridfrom must be filled.
2561                 $userfromfullname = fullname($userfrom, $canviewfullname);
2562             }
2563             foreach ($messages as $mid => $message) {
2565                 // Do not return deleted messages.
2566                 if (!$message->notification) {
2567                     if (($useridto == $USER->id and $message->timeusertodeleted) or
2568                         ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
2569                         unset($messages[$mid]);
2570                         continue;
2571                     }
2572                 }
2574                 // We need to get the user from the query.
2575                 if (empty($userfromfullname)) {
2576                     // Check for non-reply and support users.
2577                     if (core_user::is_real_user($message->useridfrom)) {
2578                         $user = new stdClass();
2579                         $user = username_load_fields_from_object($user, $message, 'userfrom');
2580                         $message->userfromfullname = fullname($user, $canviewfullname);
2581                     } else {
2582                         $user = core_user::get_user($message->useridfrom);
2583                         $message->userfromfullname = fullname($user, $canviewfullname);
2584                     }
2585                 } else {
2586                     $message->userfromfullname = $userfromfullname;
2587                 }
2589                 // We need to get the user from the query.
2590                 if (empty($usertofullname)) {
2591                     $user = new stdClass();
2592                     $user = username_load_fields_from_object($user, $message, 'userto');
2593                     $message->usertofullname = fullname($user, $canviewfullname);
2594                 } else {
2595                     $message->usertofullname = $usertofullname;
2596                 }
2598                 $message->text = message_format_message_text($message);
2599                 $messages[$mid] = (array) $message;
2600             }
2601         }
2603         $results = array(
2604             'messages' => $messages,
2605             'warnings' => $warnings
2606         );
2608         return $results;
2609     }
2611     /**
2612      * Get messages return description.
2613      *
2614      * @return external_single_structure
2615      * @since 2.8
2616      */
2617     public static function get_messages_returns() {
2618         return new external_single_structure(
2619             array(
2620                 'messages' => new external_multiple_structure(
2621                     new external_single_structure(
2622                         array(
2623                             'id' => new external_value(PARAM_INT, 'Message id'),
2624                             'useridfrom' => new external_value(PARAM_INT, 'User from id'),
2625                             'useridto' => new external_value(PARAM_INT, 'User to id'),
2626                             'subject' => new external_value(PARAM_TEXT, 'The message subject'),
2627                             'text' => new external_value(PARAM_RAW, 'The message text formated'),
2628                             'fullmessage' => new external_value(PARAM_RAW, 'The message'),
2629                             'fullmessageformat' => new external_format_value('fullmessage'),
2630                             'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
2631                             'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
2632                             'notification' => new external_value(PARAM_INT, 'Is a notification?'),
2633                             'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
2634                             'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
2635                             'timecreated' => new external_value(PARAM_INT, 'Time created'),
2636                             'timeread' => new external_value(PARAM_INT, 'Time read'),
2637                             'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
2638                             'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
2639                         ), 'message'
2640                     )
2641                 ),
2642                 'warnings' => new external_warnings()
2643             )
2644         );
2645     }
2647     /**
2648      * Mark all notifications as read parameters description.
2649      *
2650      * @return external_function_parameters
2651      * @since 3.2
2652      */
2653     public static function mark_all_notifications_as_read_parameters() {
2654         return new external_function_parameters(
2655             array(
2656                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2657                 'useridfrom' => new external_value(
2658                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2659                     VALUE_DEFAULT, 0),
2660             )
2661         );
2662     }
2664     /**
2665      * Mark all notifications as read function.
2666      *
2667      * @since  3.2
2668      * @throws invalid_parameter_exception
2669      * @throws moodle_exception
2670      * @param  int      $useridto       the user id who received the message
2671      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
2672      * @return external_description
2673      */
2674     public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2675         global $USER;
2677         $params = self::validate_parameters(
2678             self::mark_all_notifications_as_read_parameters(),
2679             array(
2680                 'useridto' => $useridto,
2681                 'useridfrom' => $useridfrom,
2682             )
2683         );
2685         $context = context_system::instance();
2686         self::validate_context($context);
2688         $useridto = $params['useridto'];
2689         $useridfrom = $params['useridfrom'];
2691         if (!empty($useridto)) {
2692             if (core_user::is_real_user($useridto)) {
2693                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2694             } else {
2695                 throw new moodle_exception('invaliduser');
2696             }
2697         }
2699         if (!empty($useridfrom)) {
2700             // We use get_user here because the from user can be the noreply or support user.
2701             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2702         }
2704         // Check if the current user is the sender/receiver or just a privileged user.
2705         if ($useridto != $USER->id and $useridfrom != $USER->id and
2706             // The deleteanymessage cap seems more reasonable here than readallmessages.
2707              !has_capability('moodle/site:deleteanymessage', $context)) {
2708             throw new moodle_exception('accessdenied', 'admin');
2709         }
2711         \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2713         return true;
2714     }
2716     /**
2717      * Mark all notifications as read return description.
2718      *
2719      * @return external_single_structure
2720      * @since 3.2
2721      */
2722     public static function mark_all_notifications_as_read_returns() {
2723         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2724     }
2726     /**
2727      * Get unread conversations count parameters description.
2728      *
2729      * @return external_function_parameters
2730      * @since 3.2
2731      */
2732     public static function get_unread_conversations_count_parameters() {
2733         return new external_function_parameters(
2734             array(
2735                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2736             )
2737         );
2738     }
2740     /**
2741      * Get unread messages count function.
2742      *
2743      * @since  3.2
2744      * @throws invalid_parameter_exception
2745      * @throws moodle_exception
2746      * @param  int      $useridto       the user id who received the message
2747      * @return external_description
2748      */
2749     public static function get_unread_conversations_count($useridto) {
2750         global $USER, $CFG;
2752         // Check if messaging is enabled.
2753         if (empty($CFG->messaging)) {
2754             throw new moodle_exception('disabled', 'message');
2755         }
2757         $params = self::validate_parameters(
2758             self::get_unread_conversations_count_parameters(),
2759             array('useridto' => $useridto)
2760         );
2762         $context = context_system::instance();
2763         self::validate_context($context);
2765         $useridto = $params['useridto'];
2767         if (!empty($useridto)) {
2768             if (core_user::is_real_user($useridto)) {
2769                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2770             } else {
2771                 throw new moodle_exception('invaliduser');
2772             }
2773         } else {
2774             $useridto = $USER->id;
2775         }
2777         // Check if the current user is the receiver or just a privileged user.
2778         if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2779             throw new moodle_exception('accessdenied', 'admin');
2780         }
2782         return \core_message\api::count_unread_conversations($userto);
2783     }
2785     /**
2786      * Get unread conversations count return description.
2787      *
2788      * @return external_single_structure
2789      * @since 3.2
2790      */
2791     public static function get_unread_conversations_count_returns() {
2792         return new external_value(PARAM_INT, 'The count of unread messages for the user');
2793     }
2795     /**
2796      * Get blocked users parameters description.
2797      *
2798      * @return external_function_parameters
2799      * @since 2.9
2800      */
2801     public static function get_blocked_users_parameters() {
2802         return new external_function_parameters(
2803             array(
2804                 'userid' => new external_value(PARAM_INT,
2805                                 'the user whose blocked users we want to retrieve',
2806                                 VALUE_REQUIRED),
2807             )
2808         );
2809     }
2811     /**
2812      * Retrieve a list of users blocked
2813      *
2814      * @param  int $userid the user whose blocked users we want to retrieve
2815      * @return external_description
2816      * @since 2.9
2817      */
2818     public static function get_blocked_users($userid) {
2819         global $CFG, $USER, $PAGE;
2821         // Warnings array, it can be empty at the end but is mandatory.
2822         $warnings = array();
2824         // Validate params.
2825         $params = array(
2826             'userid' => $userid
2827         );
2828         $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
2829         $userid = $params['userid'];
2831         // Validate context.
2832         $context = context_system::instance();
2833         self::validate_context($context);
2835         // Check if private messaging between users is allowed.
2836         if (empty($CFG->messaging)) {
2837             throw new moodle_exception('disabled', 'message');
2838         }
2840         $user = core_user::get_user($userid, '*', MUST_EXIST);
2841         core_user::require_active_user($user);
2843         // Check if we have permissions for retrieve the information.
2844         $capability = 'moodle/site:manageallmessaging';
2845         if (($USER->id != $userid) && !has_capability($capability, $context)) {
2846             throw new required_capability_exception($context, $capability, 'nopermissions', '');
2847         }
2849         // Now, we can get safely all the blocked users.
2850         $users = \core_message\api::get_blocked_users($user->id);
2852         $blockedusers = array();
2853         foreach ($users as $user) {
2854             $newuser = array(
2855                 'id' => $user->id,
2856                 'fullname' => fullname($user),
2857             );
2859             $userpicture = new user_picture($user);
2860             $userpicture->size = 1; // Size f1.
2861             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2863             $blockedusers[] = $newuser;
2864         }
2866         $results = array(
2867             'users' => $blockedusers,
2868             'warnings' => $warnings
2869         );
2870         return $results;
2871     }
2873     /**
2874      * Get blocked users return description.
2875      *
2876      * @return external_single_structure
2877      * @since 2.9
2878      */
2879     public static function get_blocked_users_returns() {
2880         return new external_single_structure(
2881             array(
2882                 'users' => new external_multiple_structure(
2883                     new external_single_structure(
2884                         array(
2885                             'id' => new external_value(PARAM_INT, 'User ID'),
2886                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2887                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
2888                         )
2889                     ),
2890                     'List of blocked users'
2891                 ),
2892                 'warnings' => new external_warnings()
2893             )
2894         );
2895     }
2897     /**
2898      * Returns description of method parameters
2899      *
2900      * @return external_function_parameters
2901      * @since 2.9
2902      */
2903     public static function mark_message_read_parameters() {
2904         return new external_function_parameters(
2905             array(
2906                 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
2907                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
2908                     VALUE_DEFAULT, 0)
2909             )
2910         );
2911     }
2913     /**
2914      * Mark a single message as read, trigger message_viewed event
2915      *
2916      * @param  int $messageid id of the message (in the message table)
2917      * @param  int $timeread timestamp for when the message should be marked read
2918      * @return external_description
2919      * @throws invalid_parameter_exception
2920      * @throws moodle_exception
2921      * @since 2.9
2922      */
2923     public static function mark_message_read($messageid, $timeread) {
2924         global $CFG, $DB, $USER;
2926         // Check if private messaging between users is allowed.
2927         if (empty($CFG->messaging)) {
2928             throw new moodle_exception('disabled', 'message');
2929         }
2931         // Warnings array, it can be empty at the end but is mandatory.
2932         $warnings = array();
2934         // Validate params.
2935         $params = array(
2936             'messageid' => $messageid,
2937             'timeread' => $timeread
2938         );
2939         $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
2941         if (empty($params['timeread'])) {
2942             $timeread = time();
2943         } else {
2944             $timeread = $params['timeread'];
2945         }
2947         // Validate context.
2948         $context = context_system::instance();
2949         self::validate_context($context);
2951         $sql = "SELECT m.*, mcm.userid as useridto
2952                   FROM {messages} m
2953             INNER JOIN {message_conversations} mc
2954                     ON m.conversationid = mc.id
2955             INNER JOIN {message_conversation_members} mcm
2956                     ON mcm.conversationid = mc.id
2957              LEFT JOIN {message_user_actions} mua
2958                     ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
2959                  WHERE mua.id is NULL
2960                    AND mcm.userid != m.useridfrom
2961                    AND m.id = ?";
2962         $messageparams = [];
2963         $messageparams[] = $USER->id;
2964         $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
2965         $messageparams[] = $params['messageid'];
2966         $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
2968         if ($message->useridto != $USER->id) {
2969             throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
2970         }
2972         \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
2974         $results = array(
2975             'messageid' => $message->id,
2976             'warnings' => $warnings
2977         );
2978         return $results;
2979     }
2981     /**
2982      * Returns description of method result value
2983      *
2984      * @return external_description
2985      * @since 2.9
2986      */
2987     public static function mark_message_read_returns() {
2988         return new external_single_structure(
2989             array(
2990                 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
2991                 'warnings' => new external_warnings()
2992             )
2993         );
2994     }
2996     /**
2997      * Returns description of method parameters
2998      *
2999      * @return external_function_parameters
3000      */
3001     public static function mark_notification_read_parameters() {
3002         return new external_function_parameters(
3003             array(
3004                 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3005                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
3006                     VALUE_DEFAULT, 0)
3007             )
3008         );
3009     }
3011     /**
3012      * Mark a single notification as read.
3013      *
3014      * This will trigger a 'notification_viewed' event.
3015      *
3016      * @param int $notificationid id of the notification
3017      * @param int $timeread timestamp for when the notification should be marked read
3018      * @return external_description
3019      * @throws invalid_parameter_exception
3020      * @throws moodle_exception
3021      */
3022     public static function mark_notification_read($notificationid, $timeread) {
3023         global $CFG, $DB, $USER;
3025         // Check if private messaging between users is allowed.
3026         if (empty($CFG->messaging)) {
3027             throw new moodle_exception('disabled', 'message');
3028         }
3030         // Warnings array, it can be empty at the end but is mandatory.
3031         $warnings = array();
3033         // Validate params.
3034         $params = array(
3035             'notificationid' => $notificationid,
3036             'timeread' => $timeread
3037         );
3038         $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
3040         if (empty($params['timeread'])) {
3041             $timeread = time();
3042         } else {
3043             $timeread = $params['timeread'];
3044         }
3046         // Validate context.
3047         $context = context_system::instance();
3048         self::validate_context($context);
3050         $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
3052         if ($notification->useridto != $USER->id) {
3053             throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
3054                 'notification as read');
3055         }
3057         \core_message\api::mark_notification_as_read($notification, $timeread);
3059         $results = array(
3060             'notificationid' => $notification->id,
3061             'warnings' => $warnings
3062         );
3064         return $results;
3065     }
3067     /**
3068      * Returns description of method result value
3069      *
3070      * @return external_description
3071      */
3072     public static function mark_notification_read_returns() {
3073         return new external_single_structure(
3074             array(
3075                 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
3076                 'warnings' => new external_warnings()
3077             )
3078         );
3079     }
3081     /**
3082      * Mark all messages as read parameters description.
3083      *
3084      * @deprecated since 3.6
3085      * @return external_function_parameters
3086      * @since 3.2
3087      */
3088     public static function mark_all_messages_as_read_parameters() {
3089         return new external_function_parameters(
3090             array(
3091                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3092                 'useridfrom' => new external_value(
3093                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3094                     VALUE_DEFAULT, 0),
3095             )
3096         );
3097     }
3099     /**
3100      * Mark all messages as read function.
3101      *
3102      * @deprecated since 3.6
3103      * @throws invalid_parameter_exception
3104      * @throws moodle_exception
3105      * @param  int      $useridto       the user id who received the message
3106      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
3107      * @return external_description
3108      * @since  3.2
3109      */
3110     public static function mark_all_messages_as_read($useridto, $useridfrom) {
3111         global $USER, $CFG;
3113         // Check if messaging is enabled.
3114         if (empty($CFG->messaging)) {
3115             throw new moodle_exception('disabled', 'message');
3116         }
3118         $params = self::validate_parameters(
3119             self::mark_all_messages_as_read_parameters(),
3120             array(
3121                 'useridto' => $useridto,
3122                 'useridfrom' => $useridfrom,
3123             )
3124         );
3126         $context = context_system::instance();
3127         self::validate_context($context);
3129         $useridto = $params['useridto'];
3130         $useridfrom = $params['useridfrom'];
3132         if (!empty($useridto)) {
3133             if (core_user::is_real_user($useridto)) {
3134                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3135             } else {
3136                 throw new moodle_exception('invaliduser');
3137             }
3138         }
3140         if (!empty($useridfrom)) {
3141             // We use get_user here because the from user can be the noreply or support user.
3142             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3143         }
3145         // Check if the current user is the sender/receiver or just a privileged user.
3146         if ($useridto != $USER->id and $useridfrom != $USER->id and
3147             // The deleteanymessage cap seems more reasonable here than readallmessages.
3148              !has_capability('moodle/site:deleteanymessage', $context)) {
3149             throw new moodle_exception('accessdenied', 'admin');
3150         }
3152         if ($useridfrom) {
3153             if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
3154                 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
3155             }
3156         } else {
3157             \core_message\api::mark_all_messages_as_read($useridto);
3158         }
3160         return true;
3161     }
3163     /**
3164      * Mark all messages as read return description.
3165      *
3166      * @deprecated since 3.6
3167      * @return external_single_structure
3168      * @since 3.2
3169      */
3170     public static function mark_all_messages_as_read_returns() {
3171         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
3172     }
3174     /**
3175      * Marking the method as deprecated.
3176      *
3177      * @return bool
3178      */
3179     public static function mark_all_messages_as_read_is_deprecated() {
3180         return true;
3181     }
3183     /**
3184      * Mark all conversation messages as read parameters description.
3185      *
3186      * @return external_function_parameters
3187      * @since 3.6
3188      */
3189     public static function mark_all_conversation_messages_as_read_parameters() {
3190         return new external_function_parameters(
3191             array(
3192                 'userid' => new external_value(PARAM_INT, 'The user id who who we are marking the messages as read for'),
3193                 'conversationid' =>
3194                     new external_value(PARAM_INT, 'The conversation id who who we are marking the messages as read for')
3195             )
3196         );
3197     }
3199     /**
3200      * Mark all conversation messages as read function.
3201      *
3202      * @param int $userid The user id of who we want to delete the conversation for
3203      * @param int $conversationid The id of the conversations
3204      * @since 3.6
3205      */
3206     public static function mark_all_conversation_messages_as_read(int $userid, int $conversationid) {
3207         global $CFG;
3209         // Check if messaging is enabled.
3210         if (empty($CFG->messaging)) {
3211             throw new moodle_exception('disabled', 'message');
3212         }
3214         $params = array(
3215             'userid' => $userid,
3216             'conversationid' => $conversationid,
3217         );
3218         $params = self::validate_parameters(self::mark_all_conversation_messages_as_read_parameters(), $params);
3220         $context = context_system::instance();
3221         self::validate_context($context);
3223         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3224         core_user::require_active_user($user);
3226         if (\core_message\api::can_mark_all_messages_as_read($params['userid'], $params['conversationid'])) {
3227             \core_message\api::mark_all_messages_as_read($params['userid'], $params['conversationid']);
3228         } else {
3229             throw new moodle_exception('accessdenied', 'admin');
3230         }
3231     }
3233     /**
3234      * Mark all conversation messages as read return description.
3235      *
3236      * @return external_warnings
3237      * @since 3.6
3238      */
3239     public static function mark_all_conversation_messages_as_read_returns() {
3240         return null;
3241     }
3243     /**
3244      * Returns description of method parameters.
3245      *
3246      * @deprecated since 3.6
3247      * @return external_function_parameters
3248      * @since 3.2
3249      */
3250     public static function delete_conversation_parameters() {
3251         return new external_function_parameters(
3252             array(
3253                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3254                 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
3255             )
3256         );
3257     }
3259     /**
3260      * Deletes a conversation.
3261      *
3262      * @deprecated since 3.6
3263      * @param int $userid The user id of who we want to delete the conversation for
3264      * @param int $otheruserid The user id of the other user in the conversation
3265      * @return array
3266      * @throws moodle_exception
3267      * @since 3.2
3268      */
3269     public static function delete_conversation($userid, $otheruserid) {
3270         global $CFG;
3272         // Check if private messaging between users is allowed.
3273         if (empty($CFG->messaging)) {
3274             throw new moodle_exception('disabled', 'message');
3275         }
3277         // Warnings array, it can be empty at the end but is mandatory.
3278         $warnings = array();
3280         // Validate params.
3281         $params = array(
3282             'userid' => $userid,
3283             'otheruserid' => $otheruserid,
3284         );
3285         $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
3287         // Validate context.
3288         $context = context_system::instance();
3289         self::validate_context($context);
3291         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3292         core_user::require_active_user($user);
3294         if (!$conversationid = \core_message\api::get_conversation_between_users([$params['userid'], $params['otheruserid']])) {
3295             return [];
3296         }
3298         if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3299             \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3300             $status = true;
3301         } else {
3302             throw new moodle_exception('You do not have permission to delete messages');
3303         }
3305         $results = array(
3306             'status' => $status,
3307             'warnings' => $warnings
3308         );
3310         return $results;
3311     }
3313     /**
3314      * Returns description of method result value.
3315      *
3316      * @deprecated since 3.6
3317      * @return external_description
3318      * @since 3.2
3319      */
3320     public static function delete_conversation_returns() {
3321         return new external_single_structure(
3322             array(
3323                 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
3324                 'warnings' => new external_warnings()
3325             )
3326         );
3327     }
3329     /**
3330      * Marking the method as deprecated.
3331      *
3332      * @return bool
3333      */
3334     public static function delete_conversation_is_deprecated() {
3335         return true;
3336     }
3338     /**
3339      * Returns description of method parameters.
3340      *
3341      * @return external_function_parameters
3342      * @since 3.6
3343      */
3344     public static function delete_conversations_by_id_parameters() {
3345         return new external_function_parameters(
3346             array(
3347                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
3348                 'conversationids' => new external_multiple_structure(
3349                     new external_value(PARAM_INT, 'The id of the conversation'),
3350                     'List of conversation IDs'
3351                 ),
3352             )
3353         );
3354     }
3356     /**
3357      * Deletes a conversation.
3358      *
3359      * @param int $userid The user id of who we want to delete the conversation for
3360      * @param int[] $conversationids The ids of the conversations
3361      * @return array
3362      * @throws moodle_exception
3363      * @since 3.6
3364      */
3365     public static function delete_conversations_by_id($userid, array $conversationids) {
3366         global $CFG;
3368         // Check if private messaging between users is allowed.
3369         if (empty($CFG->messaging)) {
3370             throw new moodle_exception('disabled', 'message');
3371         }
3373         // Validate params.
3374         $params = [
3375             'userid' => $userid,
3376             'conversationids' => $conversationids,
3377         ];
3378         $params = self::validate_parameters(self::delete_conversations_by_id_parameters(), $params);
3380         // Validate context.
3381         $context = context_system::instance();
3382         self::validate_context($context);
3384         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
3385         core_user::require_active_user($user);
3387         foreach ($params['conversationids'] as $conversationid) {
3388             if (\core_message\api::can_delete_conversation($user->id, $conversationid)) {
3389                 \core_message\api::delete_conversation_by_id($user->id, $conversationid);
3390             } else {
3391                 throw new moodle_exception("You do not have permission to delete the conversation '$conversationid'");
3392             }
3393         }
3395         return [];
3396     }
3398     /**
3399      * Returns description of method result value.
3400      *
3401      * @return external_description
3402      * @since 3.6
3403      */
3404     public static function delete_conversations_by_id_returns() {
3405         return new external_warnings();
3406     }
3408     /**
3409      * Returns description of method parameters
3410      *
3411      * @return external_function_parameters
3412      * @since 3.1
3413      */
3414     public static function delete_message_parameters() {
3415         return new external_function_parameters(
3416             array(
3417                 'messageid' => new external_value(PARAM_INT, 'The message id'),
3418                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
3419                 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
3420             )
3421         );
3422     }