MDL-65132 core_message: Added WS to delete message for all users
[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             $createdmessage = \core_message\api::send_message_to_conversation($USER->id, $params['conversationid'], $message['text'],
94                 $message['textformat']);
95             $createdmessage->text = message_format_message_text((object) [
96                 'smallmessage' => $createdmessage->text,
97                 'fullmessageformat' => external_validate_format($message['textformat']),
98                 'fullmessagetrust' => $createdmessage->fullmessagetrust
99             ]);
100             $messages[] = $createdmessage;
101         }
103         return $messages;
104     }
106     /**
107      * Returns description of method result value.
108      *
109      * @return external_description
110      * @since Moodle 3.6
111      */
112     public static function send_messages_to_conversation_returns() {
113         return new external_multiple_structure(
114             self::get_conversation_message_structure()
115         );
116     }
119     /**
120      * Returns description of method parameters
121      *
122      * @return external_function_parameters
123      * @since Moodle 2.2
124      */
125     public static function send_instant_messages_parameters() {
126         return new external_function_parameters(
127             array(
128                 'messages' => new external_multiple_structure(
129                     new external_single_structure(
130                         array(
131                             'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
132                             'text' => new external_value(PARAM_RAW, 'the text of the message'),
133                             'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
134                             '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),
135                         )
136                     )
137                 )
138             )
139         );
140     }
142     /**
143      * Send private messages from the current USER to other users
144      *
145      * @param array $messages An array of message to send.
146      * @return array
147      * @since Moodle 2.2
148      */
149     public static function send_instant_messages($messages = array()) {
150         global $CFG, $USER, $DB;
152         // Check if messaging is enabled.
153         if (empty($CFG->messaging)) {
154             throw new moodle_exception('disabled', 'message');
155         }
157         // Ensure the current user is allowed to run this function
158         $context = context_system::instance();
159         self::validate_context($context);
160         require_capability('moodle/site:sendmessage', $context);
162         // Ensure the current user is allowed to delete message for everyone.
163         $candeletemessagesforallusers = has_capability('moodle/site:deleteanymessage', $context);
165         $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
167         //retrieve all tousers of the messages
168         $receivers = array();
169         foreach($params['messages'] as $message) {
170             $receivers[] = $message['touserid'];
171         }
172         list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers);
173         $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
175         $resultmessages = array();
176         $messageids = array();
177         foreach ($params['messages'] as $message) {
178             $resultmsg = array(); //the infos about the success of the operation
180             // We are going to do some checking.
181             // Code should match /messages/index.php checks.
182             $success = true;
184             // Check the user exists.
185             if (empty($tousers[$message['touserid']])) {
186                 $success = false;
187                 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
188             }
190             // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
191             // Check if the recipient can be messaged by the sender.
192             if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
193                 $success = false;
194                 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
195             }
197             // Now we can send the message (at least try).
198             if ($success) {
199                 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
200                 $success = message_post_message($USER, $tousers[$message['touserid']],
201                         $message['text'], external_validate_format($message['textformat']));
202             }
204             // Build the resultmsg.
205             if (isset($message['clientmsgid'])) {
206                 $resultmsg['clientmsgid'] = $message['clientmsgid'];
207             }
208             if ($success) {
209                 $resultmsg['msgid'] = $success;
210                 $resultmsg['timecreated'] = time();
211                 $resultmsg['candeletemessagesforallusers'] = $candeletemessagesforallusers;
212                 $messageids[] = $success;
213             } else {
214                 // WARNINGS: for backward compatibility we return this errormessage.
215                 //          We should have thrown exceptions as these errors prevent results to be returned.
216                 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
217                 $resultmsg['msgid'] = -1;
218                 $resultmsg['errormessage'] = $errormessage;
219             }
221             $resultmessages[] = $resultmsg;
222         }
224         if (!empty($messageids)) {
225             $messagerecords = $DB->get_records_list(
226                 'messages',
227                 'id',
228                 $messageids,
229                 '',
230                 'id, conversationid, smallmessage, fullmessageformat, fullmessagetrust');
231             $resultmessages = array_map(function($resultmessage) use ($messagerecords, $USER) {
232                 $id = $resultmessage['msgid'];
233                 $resultmessage['conversationid'] = isset($messagerecords[$id]) ? $messagerecords[$id]->conversationid : null;
234                 $resultmessage['useridfrom'] = $USER->id;
235                 $resultmessage['text'] = message_format_message_text((object) [
236                     'smallmessage' => $messagerecords[$id]->smallmessage,
237                     'fullmessageformat' => external_validate_format($messagerecords[$id]->fullmessageformat),
238                     'fullmessagetrust' => $messagerecords[$id]->fullmessagetrust
239                 ]);
240                 return $resultmessage;
241             }, $resultmessages);
242         }
244         return $resultmessages;
245     }
247     /**
248      * Returns description of method result value
249      *
250      * @return external_description
251      * @since Moodle 2.2
252      */
253     public static function send_instant_messages_returns() {
254         return new external_multiple_structure(
255             new external_single_structure(
256                 array(
257                     'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds:  id of the created message if it succeeded, -1 when failed'),
258                     'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
259                     'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL),
260                     'text' => new external_value(PARAM_RAW, 'The text of the message', VALUE_OPTIONAL),
261                     'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message', VALUE_OPTIONAL),
262                     'conversationid' => new external_value(PARAM_INT, 'The conversation id for this message', VALUE_OPTIONAL),
263                     'useridfrom' => new external_value(PARAM_INT, 'The user id who sent the message', VALUE_OPTIONAL),
264                     'candeletemessagesforallusers' => new external_value(PARAM_BOOL,
265                         'If the user can delete messages in the conversation for all users', VALUE_DEFAULT, false),
266                 )
267             )
268         );
269     }
271     /**
272      * Create contacts parameters description.
273      *
274      * @deprecated since Moodle 3.6
275      * @return external_function_parameters
276      * @since Moodle 2.5
277      */
278     public static function create_contacts_parameters() {
279         return new external_function_parameters(
280             array(
281                 'userids' => new external_multiple_structure(
282                     new external_value(PARAM_INT, 'User ID'),
283                     'List of user IDs'
284                 ),
285                 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
286                     current user', VALUE_DEFAULT, 0)
287             )
288         );
289     }
291     /**
292      * Create contacts.
293      *
294      * @deprecated since Moodle 3.6
295      * @param array $userids array of user IDs.
296      * @param int $userid The id of the user we are creating the contacts for
297      * @return external_description
298      * @since Moodle 2.5
299      */
300     public static function create_contacts($userids, $userid = 0) {
301         global $CFG, $USER;
303         // Check if messaging is enabled.
304         if (empty($CFG->messaging)) {
305             throw new moodle_exception('disabled', 'message');
306         }
308         if (empty($userid)) {
309             $userid = $USER->id;
310         }
312         // Validate context.
313         $context = context_system::instance();
314         self::validate_context($context);
316         $params = array('userids' => $userids, 'userid' => $userid);
317         $params = self::validate_parameters(self::create_contacts_parameters(), $params);
319         $capability = 'moodle/site:manageallmessaging';
320         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
321             throw new required_capability_exception($context, $capability, 'nopermissions', '');
322         }
324         $warnings = array();
325         foreach ($params['userids'] as $id) {
326             if (!message_add_contact($id, 0, $params['userid'])) {
327                 $warnings[] = array(
328                     'item' => 'user',
329                     'itemid' => $id,
330                     'warningcode' => 'contactnotcreated',
331                     'message' => 'The contact could not be created'
332                 );
333             }
334         }
335         return $warnings;
336     }
338     /**
339      * Create contacts return description.
340      *
341      * @deprecated since Moodle 3.6
342      * @return external_description
343      * @since Moodle 2.5
344      */
345     public static function create_contacts_returns() {
346         return new external_warnings();
347     }
349     /**
350      * Marking the method as deprecated.
351      *
352      * @return bool
353      */
354     public static function create_contacts_is_deprecated() {
355         return true;
356     }
358     /**
359      * Delete contacts parameters description.
360      *
361      * @return external_function_parameters
362      * @since Moodle 2.5
363      */
364     public static function delete_contacts_parameters() {
365         return new external_function_parameters(
366             array(
367                 'userids' => new external_multiple_structure(
368                     new external_value(PARAM_INT, 'User ID'),
369                     'List of user IDs'
370                 ),
371                 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
372                     current user', VALUE_DEFAULT, 0)
373             )
374         );
375     }
377     /**
378      * Delete contacts.
379      *
380      * @param array $userids array of user IDs.
381      * @param int $userid The id of the user we are deleting the contacts for
382      * @return null
383      * @since Moodle 2.5
384      */
385     public static function delete_contacts($userids, $userid = 0) {
386         global $CFG, $USER;
388         // Check if messaging is enabled.
389         if (empty($CFG->messaging)) {
390             throw new moodle_exception('disabled', 'message');
391         }
393         if (empty($userid)) {
394             $userid = $USER->id;
395         }
397         // Validate context.
398         $context = context_system::instance();
399         self::validate_context($context);
401         $params = array('userids' => $userids, 'userid' => $userid);
402         $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
404         $capability = 'moodle/site:manageallmessaging';
405         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
406             throw new required_capability_exception($context, $capability, 'nopermissions', '');
407         }
409         foreach ($params['userids'] as $id) {
410             \core_message\api::remove_contact($params['userid'], $id);
411         }
413         return null;
414     }
416     /**
417      * Delete contacts return description.
418      *
419      * @return external_description
420      * @since Moodle 2.5
421      */
422     public static function delete_contacts_returns() {
423         return null;
424     }
426     /**
427      * Mute conversations parameters description.
428      *
429      * @return external_function_parameters
430      */
431     public static function mute_conversations_parameters() {
432         return new external_function_parameters(
433             [
434                 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
435                 'conversationids' => new external_multiple_structure(
436                     new external_value(PARAM_INT, 'id of the conversation', VALUE_REQUIRED)
437                 ),
438             ]
439         );
440     }
442     /**
443      * Mutes conversations.
444      *
445      * @param int $userid The id of the user who is blocking
446      * @param array $conversationids The list of conversations being muted
447      * @return external_description
448      */
449     public static function mute_conversations(int $userid, array $conversationids) {
450         global $CFG, $USER;
452         // Check if messaging is enabled.
453         if (empty($CFG->messaging)) {
454             throw new moodle_exception('disabled', 'message');
455         }
457         // Validate context.
458         $context = context_system::instance();
459         self::validate_context($context);
461         $params = ['userid' => $userid, 'conversationids' => $conversationids];
462         $params = self::validate_parameters(self::mute_conversations_parameters(), $params);
464         $capability = 'moodle/site:manageallmessaging';
465         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
466             throw new required_capability_exception($context, $capability, 'nopermissions', '');
467         }
469         foreach ($params['conversationids'] as $conversationid) {
470             if (!\core_message\api::is_conversation_muted($params['userid'], $conversationid)) {
471                 \core_message\api::mute_conversation($params['userid'], $conversationid);
472             }
473         }
475         return [];
476     }
478     /**
479      * Mute conversations return description.
480      *
481      * @return external_description
482      */
483     public static function mute_conversations_returns() {
484         return new external_warnings();
485     }
487     /**
488      * Unmute conversations parameters description.
489      *
490      * @return external_function_parameters
491      */
492     public static function unmute_conversations_parameters() {
493         return new external_function_parameters(
494             [
495                 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
496                 'conversationids' => new external_multiple_structure(
497                     new external_value(PARAM_INT, 'id of the conversation', VALUE_REQUIRED)
498                 ),
499             ]
500         );
501     }
503     /**
504      * Unmute conversations.
505      *
506      * @param int $userid The id of the user who is unblocking
507      * @param array $conversationids The list of conversations being muted
508      */
509     public static function unmute_conversations(int $userid, array $conversationids) {
510         global $CFG, $USER;
512         // Check if messaging is enabled.
513         if (empty($CFG->messaging)) {
514             throw new moodle_exception('disabled', 'message');
515         }
517         // Validate context.
518         $context = context_system::instance();
519         self::validate_context($context);
521         $params = ['userid' => $userid, 'conversationids' => $conversationids];
522         $params = self::validate_parameters(self::unmute_conversations_parameters(), $params);
524         $capability = 'moodle/site:manageallmessaging';
525         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
526             throw new required_capability_exception($context, $capability, 'nopermissions', '');
527         }
529         foreach ($params['conversationids'] as $conversationid) {
530             \core_message\api::unmute_conversation($params['userid'], $conversationid);
531         }
533         return [];
534     }
536     /**
537      * Unmute conversations return description.
538      *
539      * @return external_description
540      */
541     public static function unmute_conversations_returns() {
542         return new external_warnings();
543     }
545     /**
546      * Block user parameters description.
547      *
548      * @return external_function_parameters
549      */
550     public static function block_user_parameters() {
551         return new external_function_parameters(
552             [
553                 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
554                 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
555             ]
556         );
557     }
559     /**
560      * Blocks a user.
561      *
562      * @param int $userid The id of the user who is blocking
563      * @param int $blockeduserid The id of the user being blocked
564      * @return external_description
565      */
566     public static function block_user(int $userid, int $blockeduserid) {
567         global $CFG, $USER;
569         // Check if messaging is enabled.
570         if (empty($CFG->messaging)) {
571             throw new moodle_exception('disabled', 'message');
572         }
574         // Validate context.
575         $context = context_system::instance();
576         self::validate_context($context);
578         $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
579         $params = self::validate_parameters(self::block_user_parameters(), $params);
581         $capability = 'moodle/site:manageallmessaging';
582         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
583             throw new required_capability_exception($context, $capability, 'nopermissions', '');
584         }
586         if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
587             \core_message\api::block_user($params['userid'], $params['blockeduserid']);
588         }
590         return [];
591     }
593     /**
594      * Block user return description.
595      *
596      * @return external_description
597      */
598     public static function block_user_returns() {
599         return new external_warnings();
600     }
602     /**
603      * Unblock user parameters description.
604      *
605      * @return external_function_parameters
606      */
607     public static function unblock_user_parameters() {
608         return new external_function_parameters(
609             [
610                 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
611                 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
612             ]
613         );
614     }
616     /**
617      * Unblock user.
618      *
619      * @param int $userid The id of the user who is unblocking
620      * @param int $unblockeduserid The id of the user being unblocked
621      */
622     public static function unblock_user(int $userid, int $unblockeduserid) {
623         global $CFG, $USER;
625         // Check if messaging is enabled.
626         if (empty($CFG->messaging)) {
627             throw new moodle_exception('disabled', 'message');
628         }
630         // Validate context.
631         $context = context_system::instance();
632         self::validate_context($context);
634         $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
635         $params = self::validate_parameters(self::unblock_user_parameters(), $params);
637         $capability = 'moodle/site:manageallmessaging';
638         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
639             throw new required_capability_exception($context, $capability, 'nopermissions', '');
640         }
642         \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
644         return [];
645     }
647     /**
648      * Unblock user return description.
649      *
650      * @return external_description
651      */
652     public static function unblock_user_returns() {
653         return new external_warnings();
654     }
656     /**
657      * Block contacts parameters description.
658      *
659      * @deprecated since Moodle 3.6
660      * @return external_function_parameters
661      * @since Moodle 2.5
662      */
663     public static function block_contacts_parameters() {
664         return new external_function_parameters(
665             array(
666                 'userids' => new external_multiple_structure(
667                     new external_value(PARAM_INT, 'User ID'),
668                     'List of user IDs'
669                 ),
670                 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
671                     current user', VALUE_DEFAULT, 0)
672             )
673         );
674     }
676     /**
677      * Block contacts.
678      *
679      * @deprecated since Moodle 3.6
680      * @param array $userids array of user IDs.
681      * @param int $userid The id of the user we are blocking the contacts for
682      * @return external_description
683      * @since Moodle 2.5
684      */
685     public static function block_contacts($userids, $userid = 0) {
686         global $CFG, $USER;
688         // Check if messaging is enabled.
689         if (empty($CFG->messaging)) {
690             throw new moodle_exception('disabled', 'message');
691         }
693         if (empty($userid)) {
694             $userid = $USER->id;
695         }
697         // Validate context.
698         $context = context_system::instance();
699         self::validate_context($context);
701         $params = array('userids' => $userids, 'userid' => $userid);
702         $params = self::validate_parameters(self::block_contacts_parameters(), $params);
704         $capability = 'moodle/site:manageallmessaging';
705         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
706             throw new required_capability_exception($context, $capability, 'nopermissions', '');
707         }
709         $warnings = array();
710         foreach ($params['userids'] as $id) {
711             if (!message_block_contact($id, $params['userid'])) {
712                 $warnings[] = array(
713                     'item' => 'user',
714                     'itemid' => $id,
715                     'warningcode' => 'contactnotblocked',
716                     'message' => 'The contact could not be blocked'
717                 );
718             }
719         }
720         return $warnings;
721     }
723     /**
724      * Block contacts return description.
725      *
726      * @deprecated since Moodle 3.6
727      * @return external_description
728      * @since Moodle 2.5
729      */
730     public static function block_contacts_returns() {
731         return new external_warnings();
732     }
734     /**
735      * Marking the method as deprecated.
736      *
737      * @return bool
738      */
739     public static function block_contacts_is_deprecated() {
740         return true;
741     }
743     /**
744      * Unblock contacts parameters description.
745      *
746      * @deprecated since Moodle 3.6
747      * @return external_function_parameters
748      * @since Moodle 2.5
749      */
750     public static function unblock_contacts_parameters() {
751         return new external_function_parameters(
752             array(
753                 'userids' => new external_multiple_structure(
754                     new external_value(PARAM_INT, 'User ID'),
755                     'List of user IDs'
756                 ),
757                 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
758                     current user', VALUE_DEFAULT, 0)
759             )
760         );
761     }
763     /**
764      * Unblock contacts.
765      *
766      * @param array $userids array of user IDs.
767      * @param int $userid The id of the user we are unblocking the contacts for
768      * @return null
769      * @since Moodle 2.5
770      */
771     public static function unblock_contacts($userids, $userid = 0) {
772         global $CFG, $USER;
774         // Check if messaging is enabled.
775         if (empty($CFG->messaging)) {
776             throw new moodle_exception('disabled', 'message');
777         }
779         if (empty($userid)) {
780             $userid = $USER->id;
781         }
783         // Validate context.
784         $context = context_system::instance();
785         self::validate_context($context);
787         $params = array('userids' => $userids, 'userid' => $userid);
788         $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
790         $capability = 'moodle/site:manageallmessaging';
791         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
792             throw new required_capability_exception($context, $capability, 'nopermissions', '');
793         }
795         foreach ($params['userids'] as $id) {
796             message_unblock_contact($id, $params['userid']);
797         }
799         return null;
800     }
802     /**
803      * Unblock contacts return description.
804      *
805      * @deprecated since Moodle 3.6
806      * @return external_description
807      * @since Moodle 2.5
808      */
809     public static function unblock_contacts_returns() {
810         return null;
811     }
813     /**
814      * Marking the method as deprecated.
815      *
816      * @return bool
817      */
818     public static function unblock_contacts_is_deprecated() {
819         return true;
820     }
822     /**
823      * Returns contact requests parameters description.
824      *
825      * @return external_function_parameters
826      */
827     public static function get_contact_requests_parameters() {
828         return new external_function_parameters(
829             [
830                 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for'),
831                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
832                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
833             ]
834         );
835     }
837     /**
838      * Handles returning the contact requests for a user.
839      *
840      * This also includes the user data necessary to display information
841      * about the user.
842      *
843      * It will not include blocked users.
844      *
845      * @param int $userid The id of the user we want to get the contact requests for
846      * @param int $limitfrom
847      * @param int $limitnum
848      */
849     public static function get_contact_requests(int $userid, int $limitfrom = 0, int $limitnum = 0) {
850         global $CFG, $USER;
852         // Check if messaging is enabled.
853         if (empty($CFG->messaging)) {
854             throw new moodle_exception('disabled', 'message');
855         }
857         // Validate context.
858         $context = context_system::instance();
859         self::validate_context($context);
861         $params = [
862             'userid' => $userid,
863             'limitfrom' => $limitfrom,
864             'limitnum' => $limitnum
865         ];
866         $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
868         $capability = 'moodle/site:manageallmessaging';
869         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
870             throw new required_capability_exception($context, $capability, 'nopermissions', '');
871         }
873         return \core_message\api::get_contact_requests($params['userid'], $params['limitfrom'], $params['limitnum']);
874     }
876     /**
877      * Returns the contact requests return description.
878      *
879      * @return external_description
880      */
881     public static function get_contact_requests_returns() {
882         return new external_multiple_structure(
883             self::get_conversation_member_structure()
884         );
885     }
887     /**
888      * Returns the number of contact requests the user has received parameters description.
889      *
890      * @return external_function_parameters
891      */
892     public static function get_received_contact_requests_count_parameters() {
893         return new external_function_parameters(
894             array(
895                 'userid' => new external_value(PARAM_INT, 'The id of the user we want to return the number of ' .
896                     'received contact requests for', VALUE_REQUIRED),
897             )
898         );
899     }
901     /**
902      * Returns the number of contact requests the user has received.
903      *
904      * @param int $userid The ID of the user we want to return the number of received contact requests for
905      * @return external_value
906      */
907     public static function get_received_contact_requests_count(int $userid) {
908         global $CFG, $USER;
910         // Check if messaging is enabled.
911         if (empty($CFG->messaging)) {
912             throw new moodle_exception('disabled', 'message');
913         }
915         // Validate context.
916         $context = context_system::instance();
917         self::validate_context($context);
919         $params = [
920             'userid' => $userid,
921         ];
922         $params = self::validate_parameters(self::get_received_contact_requests_count_parameters(), $params);
924         $capability = 'moodle/site:manageallmessaging';
925         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
926             throw new required_capability_exception($context, $capability, 'nopermissions', '');
927         }
929         return \core_message\api::get_received_contact_requests_count($params['userid']);
930     }
932     /**
933      * Returns the number of contact requests the user has received return description.
934      *
935      * @return external_value
936      */
937     public static function get_received_contact_requests_count_returns() {
938         return new external_value(PARAM_INT, 'The number of received contact requests');
939     }
941     /**
942      * Returns get conversation members parameters description.
943      *
944      * @return external_function_parameters
945      */
946     public static function get_conversation_members_parameters() {
947         return new external_function_parameters(
948             [
949                 'userid' => new external_value(PARAM_INT, 'The id of the user we are performing this action on behalf of'),
950                 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation'),
951                 'includecontactrequests' => new external_value(PARAM_BOOL, 'Do we want to include contact requests?',
952                     VALUE_DEFAULT, false),
953                 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Do we want to include privacy info?',
954                     VALUE_DEFAULT, false),
955                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
956                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
957             ]
958         );
959     }
961     /**
962      * Returns a list of conversation members.
963      *
964      * @param int $userid The user we are returning the conversation members for, used by helper::get_member_info.
965      * @param int $conversationid The id of the conversation
966      * @param bool $includecontactrequests Do we want to include contact requests with this data?
967      * @param bool $includeprivacyinfo Do we want to include privacy info?
968      * @param int $limitfrom
969      * @param int $limitnum
970      * @return array
971      */
972     public static function get_conversation_members(int $userid, int $conversationid, bool $includecontactrequests = false,
973                                                     bool $includeprivacyinfo = false, int $limitfrom = 0, int $limitnum = 0) {
974         global $CFG, $USER;
976         // Check if messaging is enabled.
977         if (empty($CFG->messaging)) {
978             throw new moodle_exception('disabled', 'message');
979         }
981         // Validate context.
982         $context = context_system::instance();
983         self::validate_context($context);
985         $params = [
986             'userid' => $userid,
987             'conversationid' => $conversationid,
988             'includecontactrequests' => $includecontactrequests,
989             'includeprivacyinfo' => $includeprivacyinfo,
990             'limitfrom' => $limitfrom,
991             'limitnum' => $limitnum
992         ];
993         $params = self::validate_parameters(self::get_conversation_members_parameters(), $params);
995         $capability = 'moodle/site:manageallmessaging';
996         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
997             throw new required_capability_exception($context, $capability, 'nopermissions', '');
998         }
1000         // The user needs to be a part of the conversation before querying who the members are.
1001         if (!\core_message\api::is_user_in_conversation($params['userid'], $params['conversationid'])) {
1002             throw new moodle_exception('You are not a member of this conversation.');
1003         }
1005         return \core_message\api::get_conversation_members($params['userid'], $params['conversationid'], $params['includecontactrequests'],
1006             $params['includeprivacyinfo'], $params['limitfrom'], $params['limitnum']);
1007     }
1009     /**
1010      * Returns the get conversation members return description.
1011      *
1012      * @return external_description
1013      */
1014     public static function get_conversation_members_returns() {
1015         return new external_multiple_structure(
1016             self::get_conversation_member_structure()
1017         );
1018     }
1020     /**
1021      * Creates a contact request parameters description.
1022      *
1023      * @return external_function_parameters
1024      */
1025     public static function create_contact_request_parameters() {
1026         return new external_function_parameters(
1027             [
1028                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
1029                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
1030             ]
1031         );
1032     }
1034     /**
1035      * Creates a contact request.
1036      *
1037      * @param int $userid The id of the user who is creating the contact request
1038      * @param int $requesteduserid The id of the user being requested
1039      */
1040     public static function create_contact_request(int $userid, int $requesteduserid) {
1041         global $CFG, $USER;
1043         // Check if messaging is enabled.
1044         if (empty($CFG->messaging)) {
1045             throw new moodle_exception('disabled', 'message');
1046         }
1048         // Validate context.
1049         $context = context_system::instance();
1050         self::validate_context($context);
1052         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
1053         $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
1055         $capability = 'moodle/site:manageallmessaging';
1056         if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
1057             throw new required_capability_exception($context, $capability, 'nopermissions', '');
1058         }
1060         $result = [
1061             'warnings' => []
1062         ];
1064         if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
1065             $result['warnings'][] = [
1066                 'item' => 'user',
1067                 'itemid' => $params['requesteduserid'],
1068                 'warningcode' => 'cannotcreatecontactrequest',
1069                 'message' => 'You are unable to create a contact request for this user'
1070             ];
1071         } else {
1072             if ($requests = \core_message\api::get_contact_requests_between_users($params['userid'], $params['requesteduserid'])) {
1073                 // There should only ever be one but just in case there are multiple then we can return the first.
1074                 $result['request'] = array_shift($requests);
1075             } else {
1076                 $result['request'] = \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
1077             }
1078         }
1080         return $result;
1081     }
1083     /**
1084      * Creates a contact request return description.
1085      *
1086      * @return external_description
1087      */
1088     public static function create_contact_request_returns() {
1089         return new external_single_structure(
1090             array(
1091                 'request' => new external_single_structure(
1092                     array(
1093                         'id' => new external_value(PARAM_INT, 'Message id'),
1094                         'userid' => new external_value(PARAM_INT, 'User from id'),
1095                         'requesteduserid' => new external_value(PARAM_INT, 'User to id'),
1096                         'timecreated' => new external_value(PARAM_INT, 'Time created'),
1097                     ),
1098                     'request record',
1099                     VALUE_OPTIONAL
1100                 ),
1101                 'warnings' => new external_warnings()
1102             )
1103         );
1104     }
1106     /**
1107      * Confirm a contact request parameters description.
1108      *
1109      * @return external_function_parameters
1110      */
1111     public static function confirm_contact_request_parameters() {
1112         return new external_function_parameters(
1113             [
1114                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
1115                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
1116             ]
1117         );
1118     }
1120     /**
1121      * Confirm a contact request.
1122      *
1123      * @param int $userid The id of the user who is creating the contact request
1124      * @param int $requesteduserid The id of the user being requested
1125      */
1126     public static function confirm_contact_request(int $userid, int $requesteduserid) {
1127         global $CFG, $USER;
1129         // Check if messaging is enabled.
1130         if (empty($CFG->messaging)) {
1131             throw new moodle_exception('disabled', 'message');
1132         }
1134         // Validate context.
1135         $context = context_system::instance();
1136         self::validate_context($context);
1138         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
1139         $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
1141         $capability = 'moodle/site:manageallmessaging';
1142         if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
1143             throw new required_capability_exception($context, $capability, 'nopermissions', '');
1144         }
1146         \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
1148         return [];
1149     }
1151     /**
1152      * Confirm a contact request return description.
1153      *
1154      * @return external_description
1155      */
1156     public static function confirm_contact_request_returns() {
1157         return new external_warnings();
1158     }
1160     /**
1161      * Declines a contact request parameters description.
1162      *
1163      * @return external_function_parameters
1164      */
1165     public static function decline_contact_request_parameters() {
1166         return new external_function_parameters(
1167             [
1168                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
1169                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
1170             ]
1171         );
1172     }
1174     /**
1175      * Declines a contact request.
1176      *
1177      * @param int $userid The id of the user who is creating the contact request
1178      * @param int $requesteduserid The id of the user being requested
1179      */
1180     public static function decline_contact_request(int $userid, int $requesteduserid) {
1181         global $CFG, $USER;
1183         // Check if messaging is enabled.
1184         if (empty($CFG->messaging)) {
1185             throw new moodle_exception('disabled', 'message');
1186         }
1188         // Validate context.
1189         $context = context_system::instance();
1190         self::validate_context($context);
1192         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
1193         $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
1195         $capability = 'moodle/site:manageallmessaging';
1196         if (($USER->id != $params['requesteduserid']) && !has_capability($capability, $context)) {
1197             throw new required_capability_exception($context, $capability, 'nopermissions', '');
1198         }
1200         \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
1202         return [];
1203     }
1205     /**
1206      * Declines a contact request return description.
1207      *
1208      * @return external_description
1209      */
1210     public static function decline_contact_request_returns() {
1211         return new external_warnings();
1212     }
1214     /**
1215      * Return the structure of a message area contact.
1216      *
1217      * @return external_single_structure
1218      * @since Moodle 3.2
1219      */
1220     private static function get_messagearea_contact_structure() {
1221         return new external_single_structure(
1222             array(
1223                 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
1224                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1225                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1226                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1227                 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
1228                 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
1229                 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
1230                 'lastmessagedate' => new external_value(PARAM_INT, 'Timestamp for last message', VALUE_DEFAULT, null),
1231                 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
1232                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1233                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1234                 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
1235                 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1236                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1237                     VALUE_DEFAULT, null),
1238                 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation', VALUE_DEFAULT, null),
1239             )
1240         );
1241     }
1243     /**
1244      * Return the structure of a conversation.
1245      *
1246      * @return external_single_structure
1247      * @since Moodle 3.6
1248      */
1249     private static function get_conversation_structure() {
1250         return new external_single_structure(
1251             array(
1252                 'id' => new external_value(PARAM_INT, 'The conversation id'),
1253                 'name' => new external_value(PARAM_TEXT, 'The conversation name, if set', VALUE_DEFAULT, null),
1254                 'subname' => new external_value(PARAM_TEXT, 'A subtitle for the conversation name, if set', VALUE_DEFAULT, null),
1255                 'imageurl' => new external_value(PARAM_URL, 'A link to the conversation picture, if set', VALUE_DEFAULT, null),
1256                 'type' => new external_value(PARAM_INT, 'The type of the conversation (1=individual,2=group,3=self)'),
1257                 'membercount' => new external_value(PARAM_INT, 'Total number of conversation members'),
1258                 'ismuted' => new external_value(PARAM_BOOL, 'If the user muted this conversation'),
1259                 'isfavourite' => new external_value(PARAM_BOOL, 'If the user marked this conversation as a favourite'),
1260                 'isread' => new external_value(PARAM_BOOL, 'If the user has read all messages in the conversation'),
1261                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
1262                     VALUE_DEFAULT, null),
1263                 'members' => new external_multiple_structure(
1264                     self::get_conversation_member_structure()
1265                 ),
1266                 'messages' => new external_multiple_structure(
1267                     self::get_conversation_message_structure()
1268                 ),
1269                 'candeletemessagesforallusers' => new external_value(PARAM_BOOL,
1270                     'If the user can delete messages in the conversation for all users', VALUE_DEFAULT, false),
1271             )
1272         );
1273     }
1275     /**
1276      * Return the structure of a conversation member.
1277      *
1278      * @return external_single_structure
1279      * @since Moodle 3.6
1280      */
1281     private static function get_conversation_member_structure() {
1282         $result = [
1283             'id' => new external_value(PARAM_INT, 'The user id'),
1284             'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1285             'profileurl' => new external_value(PARAM_URL, 'The link to the user\'s profile page'),
1286             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1287             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1288             'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1289             'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1290             'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
1291             'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
1292             'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
1293             'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
1294             'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
1295         ];
1297         $result['contactrequests'] = new external_multiple_structure(
1298             new external_single_structure(
1299                 [
1300                     'id' => new external_value(PARAM_INT, 'The id of the contact request'),
1301                     'userid' => new external_value(PARAM_INT, 'The id of the user who created the contact request'),
1302                     'requesteduserid' => new external_value(PARAM_INT, 'The id of the user confirming the request'),
1303                     'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the contact request'),
1304                 ]
1305             ), 'The contact requests', VALUE_OPTIONAL
1306         );
1308         $result['conversations'] = new external_multiple_structure(new external_single_structure(
1309             array(
1310                 'id' => new external_value(PARAM_INT, 'Conversations id'),
1311                 'type' => new external_value(PARAM_INT, 'Conversation type: private or public'),
1312                 'name' => new external_value(PARAM_TEXT, 'Multilang compatible conversation name'. VALUE_OPTIONAL),
1313                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the conversation'),
1314             ), 'information about conversation', VALUE_OPTIONAL),
1315             'Conversations between users', VALUE_OPTIONAL
1316         );
1318         return new external_single_structure(
1319             $result
1320         );
1321     }
1323     /**
1324      * Return the structure of a message area message.
1325      *
1326      * @return external_single_structure
1327      * @since Moodle 3.6
1328      */
1329     private static function get_conversation_message_structure() {
1330         return new external_single_structure(
1331             array(
1332                 'id' => new external_value(PARAM_INT, 'The id of the message'),
1333                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1334                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1335                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1336             )
1337         );
1338     }
1340     /**
1341      * Return the structure of a message area message.
1342      *
1343      * @return external_single_structure
1344      * @since Moodle 3.2
1345      */
1346     private static function get_messagearea_message_structure() {
1347         return new external_single_structure(
1348             array(
1349                 'id' => new external_value(PARAM_INT, 'The id of the message'),
1350                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
1351                 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
1352                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
1353                 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
1354                 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
1355                 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
1356                 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
1357                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
1358                 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
1359             )
1360         );
1361     }
1363     /**
1364      * Get messagearea search users in course parameters.
1365      *
1366      * @deprecated since 3.6
1367      *
1368      * @return external_function_parameters
1369      * @since 3.2
1370      */
1371     public static function data_for_messagearea_search_users_in_course_parameters() {
1372         return new external_function_parameters(
1373             array(
1374                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1375                 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
1376                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1377                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1378                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1379             )
1380         );
1381     }
1383     /**
1384      * Get messagearea search users in course results.
1385      *
1386      * @deprecated since 3.6
1387      *
1388      * @param int $userid The id of the user who is performing the search
1389      * @param int $courseid The id of the course
1390      * @param string $search The string being searched
1391      * @param int $limitfrom
1392      * @param int $limitnum
1393      * @return stdClass
1394      * @throws moodle_exception
1395      * @since 3.2
1396      */
1397     public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
1398                                                                        $limitnum = 0) {
1399         global $CFG, $PAGE, $USER;
1401         // Check if messaging is enabled.
1402         if (empty($CFG->messaging)) {
1403             throw new moodle_exception('disabled', 'message');
1404         }
1406         $systemcontext = context_system::instance();
1408         $params = array(
1409             'userid' => $userid,
1410             'courseid' => $courseid,
1411             'search' => $search,
1412             'limitfrom' => $limitfrom,
1413             'limitnum' => $limitnum
1414         );
1415         $params = self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
1416         self::validate_context($systemcontext);
1418         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1419             throw new moodle_exception('You do not have permission to perform this action.');
1420         }
1422         $users = \core_message\api::search_users_in_course(
1423             $params['userid'],
1424             $params['courseid'],
1425             $params['search'],
1426             $params['limitfrom'],
1427             $params['limitnum']
1428         );
1429         $results = new \core_message\output\messagearea\user_search_results($users);
1431         $renderer = $PAGE->get_renderer('core_message');
1432         return $results->export_for_template($renderer);
1433     }
1435     /**
1436      * Get messagearea search users in course returns.
1437      *
1438      * @deprecated since 3.6
1439      *
1440      * @return external_single_structure
1441      * @since 3.2
1442      */
1443     public static function data_for_messagearea_search_users_in_course_returns() {
1444         return new external_single_structure(
1445             array(
1446                 'contacts' => new external_multiple_structure(
1447                     self::get_messagearea_contact_structure()
1448                 ),
1449             )
1450         );
1451     }
1453     /**
1454      * Marking the method as deprecated.
1455      *
1456      * @return bool
1457      */
1458     public static function data_for_messagearea_search_users_in_course_is_deprecated() {
1459         return true;
1460     }
1462     /**
1463      * Get messagearea search users parameters.
1464      *
1465      * @deprecated since 3.6
1466      *
1467      * @return external_function_parameters
1468      * @since 3.2
1469      */
1470     public static function data_for_messagearea_search_users_parameters() {
1471         return new external_function_parameters(
1472             array(
1473                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1474                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1475                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1476             )
1477         );
1478     }
1480     /**
1481      * Get messagearea search users results.
1482      *
1483      * @deprecated since 3.6
1484      *
1485      * @param int $userid The id of the user who is performing the search
1486      * @param string $search The string being searched
1487      * @param int $limitnum
1488      * @return stdClass
1489      * @throws moodle_exception
1490      * @since 3.2
1491      */
1492     public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1493         global $CFG, $PAGE, $USER;
1495         // Check if messaging is enabled.
1496         if (empty($CFG->messaging)) {
1497             throw new moodle_exception('disabled', 'message');
1498         }
1500         $systemcontext = context_system::instance();
1502         $params = array(
1503             'userid' => $userid,
1504             'search' => $search,
1505             'limitnum' => $limitnum
1506         );
1507         $params = self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1508         self::validate_context($systemcontext);
1510         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1511             throw new moodle_exception('You do not have permission to perform this action.');
1512         }
1514         list($contacts, $courses, $noncontacts) = \core_message\api::search_users(
1515             $params['userid'],
1516             $params['search'],
1517             $params['limitnum']
1518         );
1520         $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1522         $renderer = $PAGE->get_renderer('core_message');
1523         return $search->export_for_template($renderer);
1524     }
1526     /**
1527      * Get messagearea search users returns.
1528      *
1529      * @deprecated since 3.6
1530      *
1531      * @return external_single_structure
1532      * @since 3.2
1533      */
1534     public static function data_for_messagearea_search_users_returns() {
1535         return new external_single_structure(
1536             array(
1537                 'contacts' => new external_multiple_structure(
1538                     self::get_messagearea_contact_structure()
1539                 ),
1540                 'courses' => new external_multiple_structure(
1541                     new external_single_structure(
1542                         array(
1543                             'id' => new external_value(PARAM_INT, 'The course id'),
1544                             'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1545                             'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1546                         )
1547                     )
1548                 ),
1549                 'noncontacts' => new external_multiple_structure(
1550                     self::get_messagearea_contact_structure()
1551                 )
1552             )
1553         );
1554     }
1556     /**
1557      * Marking the method as deprecated.
1558      *
1559      * @return bool
1560      */
1561     public static function data_for_messagearea_search_users_is_deprecated() {
1562         return true;
1563     }
1565     /**
1566      * Get messagearea message search users parameters.
1567      *
1568      * @return external_function_parameters
1569      * @since 3.6
1570      */
1571     public static function message_search_users_parameters() {
1572         return new external_function_parameters(
1573             array(
1574                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1575                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1576                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1577                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1578             )
1579         );
1580     }
1582     /**
1583      * Get search users results.
1584      *
1585      * @param int $userid The id of the user who is performing the search
1586      * @param string $search The string being searched
1587      * @param int $limitfrom
1588      * @param int $limitnum
1589      * @return array
1590      * @throws moodle_exception
1591      * @since 3.6
1592      */
1593     public static function message_search_users($userid, $search, $limitfrom = 0, $limitnum = 0) {
1594         global $USER;
1596         $systemcontext = context_system::instance();
1598         $params = array(
1599             'userid' => $userid,
1600             'search' => $search,
1601             'limitfrom' => $limitfrom,
1602             'limitnum' => $limitnum
1603         );
1604         $params = self::validate_parameters(self::message_search_users_parameters(), $params);
1605         self::validate_context($systemcontext);
1607         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1608             throw new moodle_exception('You do not have permission to perform this action.');
1609         }
1611         list($contacts, $noncontacts) = \core_message\api::message_search_users(
1612             $params['userid'],
1613             $params['search'],
1614             $params['limitfrom'],
1615             $params['limitnum']);
1617         return array('contacts' => $contacts, 'noncontacts' => $noncontacts);
1618     }
1620     /**
1621      * Get messagearea message search users returns.
1622      *
1623      * @return external_single_structure
1624      * @since 3.2
1625      */
1626     public static function message_search_users_returns() {
1627         return new external_single_structure(
1628             array(
1629                 'contacts' => new external_multiple_structure(
1630                     self::get_conversation_member_structure()
1631                 ),
1632                 'noncontacts' => new external_multiple_structure(
1633                     self::get_conversation_member_structure()
1634                 )
1635             )
1636         );
1637     }
1639     /**
1640      * Get messagearea search messages parameters.
1641      *
1642      * @return external_function_parameters
1643      * @since 3.2
1644      */
1645     public static function data_for_messagearea_search_messages_parameters() {
1646         return new external_function_parameters(
1647             array(
1648                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1649                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1650                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1651                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1652             )
1653         );
1654     }
1656     /**
1657      * Get messagearea search messages results.
1658      *
1659      * @param int $userid The id of the user who is performing the search
1660      * @param string $search The string being searched
1661      * @param int $limitfrom
1662      * @param int $limitnum
1663      * @return stdClass
1664      * @throws moodle_exception
1665      * @since 3.2
1666      */
1667     public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1668         global $CFG, $USER;
1670         // Check if messaging is enabled.
1671         if (empty($CFG->messaging)) {
1672             throw new moodle_exception('disabled', 'message');
1673         }
1675         $systemcontext = context_system::instance();
1677         $params = array(
1678             'userid' => $userid,
1679             'search' => $search,
1680             'limitfrom' => $limitfrom,
1681             'limitnum' => $limitnum
1683         );
1684         $params = self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1685         self::validate_context($systemcontext);
1687         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1688             throw new moodle_exception('You do not have permission to perform this action.');
1689         }
1691         $messages = \core_message\api::search_messages(
1692             $params['userid'],
1693             $params['search'],
1694             $params['limitfrom'],
1695             $params['limitnum']
1696         );
1698         $data = new \stdClass();
1699         $data->contacts = [];
1700         foreach ($messages as $message) {
1701             $contact = new \stdClass();
1702             $contact->userid = $message->userid;
1703             $contact->fullname = $message->fullname;
1704             $contact->profileimageurl = $message->profileimageurl;
1705             $contact->profileimageurlsmall = $message->profileimageurlsmall;
1706             $contact->messageid = $message->messageid;
1707             $contact->ismessaging = $message->ismessaging;
1708             $contact->sentfromcurrentuser = false;
1709             if ($message->lastmessage) {
1710                 if ($message->userid !== $message->useridfrom) {
1711                     $contact->sentfromcurrentuser = true;
1712                 }
1713                 $contact->lastmessage = shorten_text($message->lastmessage, 60);
1714             } else {
1715                 $contact->lastmessage = null;
1716             }
1717             $contact->lastmessagedate = $message->lastmessagedate;
1718             $contact->showonlinestatus = is_null($message->isonline) ? false : true;
1719             $contact->isonline = $message->isonline;
1720             $contact->isblocked = $message->isblocked;
1721             $contact->isread = $message->isread;
1722             $contact->unreadcount = $message->unreadcount;
1723             $contact->conversationid = $message->conversationid;
1725             $data->contacts[] = $contact;
1726         }
1728         return $data;
1729     }
1731     /**
1732      * Get messagearea search messages returns.
1733      *
1734      * @return external_single_structure
1735      * @since 3.2
1736      */
1737     public static function data_for_messagearea_search_messages_returns() {
1738         return new external_single_structure(
1739             array(
1740                 'contacts' => new external_multiple_structure(
1741                     self::get_messagearea_contact_structure()
1742                 )
1743             )
1744         );
1745     }
1747     /**
1748      * Get conversations parameters.
1749      *
1750      * @return external_function_parameters
1751      * @since 3.6
1752      */
1753     public static function get_conversations_parameters() {
1754         return new external_function_parameters(
1755             array(
1756                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1757                 'limitfrom' => new external_value(PARAM_INT, 'The offset to start at', VALUE_DEFAULT, 0),
1758                 'limitnum' => new external_value(PARAM_INT, 'Limit number of conversations to this', VALUE_DEFAULT, 0),
1759                 'type' => new external_value(PARAM_INT, 'Filter by type', VALUE_DEFAULT, null),
1760                 'favourites' => new external_value(PARAM_BOOL, 'Whether to restrict the results to contain NO favourite
1761                 conversations (false), ONLY favourite conversation (true), or ignore any restriction altogether (null)',
1762                     VALUE_DEFAULT, null),
1763                 'mergeself' => new external_value(PARAM_BOOL, 'Whether to include self-conversations (true) or ONLY private
1764                     conversations (false) when private conversations are requested.',
1765                     VALUE_DEFAULT, false),
1766             )
1767         );
1768     }
1770     /**
1771      * Get the list of conversations for the user.
1772      *
1773      * @param int $userid The id of the user who is performing the search
1774      * @param int $limitfrom
1775      * @param int $limitnum
1776      * @param int|null $type
1777      * @param bool|null $favourites
1778      * @param bool $mergeself whether to include self-conversations (true) or ONLY private conversations (false)
1779      *             when private conversations are requested.
1780      * @return stdClass
1781      * @throws \moodle_exception if the messaging feature is disabled on the site.
1782      * @since 3.2
1783      */
1784     public static function get_conversations($userid, $limitfrom = 0, $limitnum = 0, int $type = null, bool $favourites = null,
1785             bool $mergeself = false) {
1786         global $CFG, $USER;
1788         // All the standard BL checks.
1789         if (empty($CFG->messaging)) {
1790             throw new moodle_exception('disabled', 'message');
1791         }
1793         $params = array(
1794             'userid' => $userid,
1795             'limitfrom' => $limitfrom,
1796             'limitnum' => $limitnum,
1797             'type' => $type,
1798             'favourites' => $favourites,
1799             'mergeself' => $mergeself
1800         );
1801         $params = self::validate_parameters(self::get_conversations_parameters(), $params);
1803         $systemcontext = context_system::instance();
1804         self::validate_context($systemcontext);
1806         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1807             throw new moodle_exception('You do not have permission to perform this action.');
1808         }
1810         $conversations = \core_message\api::get_conversations(
1811             $params['userid'],
1812             $params['limitfrom'],
1813             $params['limitnum'],
1814             $params['type'],
1815             $params['favourites'],
1816             $params['mergeself']
1817         );
1819         return (object) ['conversations' => $conversations];
1820     }
1822     /**
1823      * Get conversations returns.
1824      *
1825      * @return external_single_structure
1826      * @since 3.6
1827      */
1828     public static function get_conversations_returns() {
1829         return new external_single_structure(
1830             [
1831                 'conversations' => new external_multiple_structure(
1832                     self::get_conversation_structure(true)
1833                 )
1834             ]
1835         );
1836     }
1838     /**
1839      * Get conversation parameters.
1840      *
1841      * @return external_function_parameters
1842      */
1843     public static function get_conversation_parameters() {
1844         return new external_function_parameters(
1845             array(
1846                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1847                 'conversationid' => new external_value(PARAM_INT, 'The id of the conversation to fetch'),
1848                 'includecontactrequests' => new external_value(PARAM_BOOL, 'Include contact requests in the members'),
1849                 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Include privacy info in the members'),
1850                 'memberlimit' => new external_value(PARAM_INT, 'Limit for number of members', VALUE_DEFAULT, 0),
1851                 'memberoffset' => new external_value(PARAM_INT, 'Offset for member list', VALUE_DEFAULT, 0),
1852                 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
1853                 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
1854                 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
1855             )
1856         );
1857     }
1859     /**
1860      * Get a single conversation.
1861      *
1862      * @param int $userid The user id to get the conversation for
1863      * @param int $conversationid The id of the conversation to fetch
1864      * @param bool $includecontactrequests Should contact requests be included between members
1865      * @param bool $includeprivacyinfo Should privacy info be included between members
1866      * @param int $memberlimit Limit number of members to load
1867      * @param int $memberoffset Offset members by this amount
1868      * @param int $messagelimit Limit number of messages to load
1869      * @param int $messageoffset Offset the messages
1870      * @param bool $newestmessagesfirst Order messages by newest first
1871      * @return stdClass
1872      * @throws \moodle_exception if the messaging feature is disabled on the site.
1873      */
1874     public static function get_conversation(
1875         int $userid,
1876         int $conversationid,
1877         bool $includecontactrequests = false,
1878         bool $includeprivacyinfo = false,
1879         int $memberlimit = 0,
1880         int $memberoffset = 0,
1881         int $messagelimit = 0,
1882         int $messageoffset = 0,
1883         bool $newestmessagesfirst = true
1884     ) {
1885         global $CFG, $DB, $USER;
1887         // All the standard BL checks.
1888         if (empty($CFG->messaging)) {
1889             throw new moodle_exception('disabled', 'message');
1890         }
1892         $params = [
1893             'userid' => $userid,
1894             'conversationid' => $conversationid,
1895             'includecontactrequests' => $includecontactrequests,
1896             'includeprivacyinfo' => $includeprivacyinfo,
1897             'memberlimit' => $memberlimit,
1898             'memberoffset' => $memberoffset,
1899             'messagelimit' => $messagelimit,
1900             'messageoffset' => $messageoffset,
1901             'newestmessagesfirst' => $newestmessagesfirst
1902         ];
1903         self::validate_parameters(self::get_conversation_parameters(), $params);
1905         $systemcontext = context_system::instance();
1906         self::validate_context($systemcontext);
1908         $conversation = \core_message\api::get_conversation(
1909             $params['userid'],
1910             $params['conversationid'],
1911             $params['includecontactrequests'],
1912             $params['includeprivacyinfo'],
1913             $params['memberlimit'],
1914             $params['memberoffset'],
1915             $params['messagelimit'],
1916             $params['messageoffset'],
1917             $params['newestmessagesfirst']
1918         );
1920         if ($conversation) {
1921             return $conversation;
1922         } else {
1923             // We have to throw an exception here because the external functions annoyingly
1924             // don't accept null to be returned for a single structure.
1925             throw new \moodle_exception('errorconversationdoesnotexist', 'message');
1926         }
1927     }
1929     /**
1930      * Get conversation returns.
1931      *
1932      * @return external_single_structure
1933      */
1934     public static function get_conversation_returns() {
1935         return self::get_conversation_structure();
1936     }
1938     /**
1939      * Get conversation parameters.
1940      *
1941      * @return external_function_parameters
1942      */
1943     public static function get_conversation_between_users_parameters() {
1944         return new external_function_parameters(
1945             array(
1946                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1947                 'otheruserid' => new external_value(PARAM_INT, 'The other user id'),
1948                 'includecontactrequests' => new external_value(PARAM_BOOL, 'Include contact requests in the members'),
1949                 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'Include privacy info in the members'),
1950                 'memberlimit' => new external_value(PARAM_INT, 'Limit for number of members', VALUE_DEFAULT, 0),
1951                 'memberoffset' => new external_value(PARAM_INT, 'Offset for member list', VALUE_DEFAULT, 0),
1952                 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
1953                 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
1954                 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
1955             )
1956         );
1957     }
1959     /**
1960      * Get a single conversation between users.
1961      *
1962      * @param int $userid The user id to get the conversation for
1963      * @param int $otheruserid The other user id
1964      * @param bool $includecontactrequests Should contact requests be included between members
1965      * @param bool $includeprivacyinfo Should privacy info be included between members
1966      * @param int $memberlimit Limit number of members to load
1967      * @param int $memberoffset Offset members by this amount
1968      * @param int $messagelimit Limit number of messages to load
1969      * @param int $messageoffset Offset the messages
1970      * @param bool $newestmessagesfirst Order messages by newest first
1971      * @return stdClass
1972      * @throws \moodle_exception if the messaging feature is disabled on the site.
1973      */
1974     public static function get_conversation_between_users(
1975         int $userid,
1976         int $otheruserid,
1977         bool $includecontactrequests = false,
1978         bool $includeprivacyinfo = false,
1979         int $memberlimit = 0,
1980         int $memberoffset = 0,
1981         int $messagelimit = 0,
1982         int $messageoffset = 0,
1983         bool $newestmessagesfirst = true
1984     ) {
1985         global $CFG, $DB, $USER;
1987         // All the standard BL checks.
1988         if (empty($CFG->messaging)) {
1989             throw new moodle_exception('disabled', 'message');
1990         }
1992         $params = [
1993             'userid' => $userid,
1994             'otheruserid' => $otheruserid,
1995             'includecontactrequests' => $includecontactrequests,
1996             'includeprivacyinfo' => $includeprivacyinfo,
1997             'memberlimit' => $memberlimit,
1998             'memberoffset' => $memberoffset,
1999             'messagelimit' => $messagelimit,
2000             'messageoffset' => $messageoffset,
2001             'newestmessagesfirst' => $newestmessagesfirst
2002         ];
2003         self::validate_parameters(self::get_conversation_between_users_parameters(), $params);
2005         $systemcontext = context_system::instance();
2006         self::validate_context($systemcontext);
2008         $conversationid = \core_message\api::get_conversation_between_users([$params['userid'], $params['otheruserid']]);
2009         $conversation = null;
2011         if ($conversationid) {
2012             $conversation = \core_message\api::get_conversation(
2013                 $params['userid'],
2014                 $conversationid,
2015                 $params['includecontactrequests'],
2016                 $params['includeprivacyinfo'],
2017                 $params['memberlimit'],
2018                 $params['memberoffset'],
2019                 $params['messagelimit'],
2020                 $params['messageoffset'],
2021                 $params['newestmessagesfirst']
2022             );
2023         }
2025         if ($conversation) {
2026             return $conversation;
2027         } else {
2028             // We have to throw an exception here because the external functions annoyingly
2029             // don't accept null to be returned for a single structure.
2030             throw new \moodle_exception('errorconversationdoesnotexist', 'message');
2031         }
2032     }
2034     /**
2035      * Get conversation returns.
2036      *
2037      * @return external_single_structure
2038      */
2039     public static function get_conversation_between_users_returns() {
2040         return self::get_conversation_structure(true);
2041     }
2043     /**
2044      * Get self-conversation parameters.
2045      *
2046      * @return external_function_parameters
2047      */
2048     public static function get_self_conversation_parameters() {
2049         return new external_function_parameters(
2050             array(
2051                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing self-conversations for'),
2052                 'messagelimit' => new external_value(PARAM_INT, 'Limit for number of messages', VALUE_DEFAULT, 100),
2053                 'messageoffset' => new external_value(PARAM_INT, 'Offset for messages list', VALUE_DEFAULT, 0),
2054                 'newestmessagesfirst' => new external_value(PARAM_BOOL, 'Order messages by newest first', VALUE_DEFAULT, true)
2055             )
2056         );
2057     }
2059     /**
2060      * Get a single self-conversation.
2061      *
2062      * @param int $userid The user id to get the self-conversation for
2063      * @param int $messagelimit Limit number of messages to load
2064      * @param int $messageoffset Offset the messages
2065      * @param bool $newestmessagesfirst Order messages by newest first
2066      * @return stdClass
2067      * @throws \moodle_exception if the messaging feature is disabled on the site.
2068      * @since Moodle 3.7
2069      */
2070     public static function get_self_conversation(
2071         int $userid,
2072         int $messagelimit = 0,
2073         int $messageoffset = 0,
2074         bool $newestmessagesfirst = true
2075     ) {
2076         global $CFG;
2078         // All the standard BL checks.
2079         if (empty($CFG->messaging)) {
2080             throw new moodle_exception('disabled', 'message');
2081         }
2083         $params = [
2084             'userid' => $userid,
2085             'messagelimit' => $messagelimit,
2086             'messageoffset' => $messageoffset,
2087             'newestmessagesfirst' => $newestmessagesfirst
2088         ];
2089         self::validate_parameters(self::get_self_conversation_parameters(), $params);
2091         $systemcontext = context_system::instance();
2092         self::validate_context($systemcontext);
2094         $conversation = \core_message\api::get_self_conversation($params['userid']);
2096         if ($conversation) {
2097             $conversation = \core_message\api::get_conversation(
2098                 $params['userid'],
2099                 $conversation->id,
2100                 false,
2101                 false,
2102                 0,
2103                 0,
2104                 $params['messagelimit'],
2105                 $params['messageoffset'],
2106                 $params['newestmessagesfirst']
2107             );
2108         }
2110         if ($conversation) {
2111             return $conversation;
2112         } else {
2113             // We have to throw an exception here because the external functions annoyingly
2114             // don't accept null to be returned for a single structure.
2115             throw new \moodle_exception('errorconversationdoesnotexist', 'message');
2116         }
2117     }
2119     /**
2120      * Get conversation returns.
2121      *
2122      * @return external_single_structure
2123      */
2124     public static function get_self_conversation_returns() {
2125         return self::get_conversation_structure();
2126     }
2128     /**
2129      * The messagearea conversations parameters.
2130      *
2131      * @deprecated since 3.6
2132      * @return external_function_parameters
2133      * @since 3.2
2134      */
2135     public static function data_for_messagearea_conversations_parameters() {
2136         return new external_function_parameters(
2137             array(
2138                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
2139                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2140                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
2141             )
2142         );
2143     }
2145     /**
2146      * Get messagearea conversations.
2147      *
2148      * NOTE FOR FINAL DEPRECATION:
2149      * When removing this method, please also consider removal of get_conversations_legacy_formatter()
2150      * from the \core_message\helper class. This helper method was used solely to format the new get_conversations() return data
2151      * into the old format used here, and in message/index.php. If we no longer need either of these, then that method can be
2152      * removed.
2153      *
2154      * @deprecated since 3.6
2155      * @param int $userid The id of the user who we are viewing conversations for
2156      * @param int $limitfrom
2157      * @param int $limitnum
2158      * @return stdClass
2159      * @throws moodle_exception
2160      * @since 3.2
2161      */
2162     public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
2163         global $CFG, $PAGE, $USER;
2165         // Check if messaging is enabled.
2166         if (empty($CFG->messaging)) {
2167             throw new moodle_exception('disabled', 'message');
2168         }
2170         $systemcontext = context_system::instance();
2172         $params = array(
2173             'userid' => $userid,
2174             'limitfrom' => $limitfrom,
2175             'limitnum' => $limitnum
2176         );
2177         $params = self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
2178         self::validate_context($systemcontext);
2180         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2181             throw new moodle_exception('You do not have permission to perform this action.');
2182         }
2184         $conversations = \core_message\api::get_conversations($params['userid'], $params['limitfrom'], $params['limitnum']);
2186         // Format the conversations in the legacy style, as the get_conversations method has since been changed.
2187         $conversations = \core_message\helper::get_conversations_legacy_formatter($conversations);
2189         $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
2191         $renderer = $PAGE->get_renderer('core_message');
2192         return $conversations->export_for_template($renderer);
2193     }
2195     /**
2196      * The messagearea conversations return structure.
2197      *
2198      * @deprecated since 3.6
2199      * @return external_single_structure
2200      * @since 3.2
2201      */
2202     public static function data_for_messagearea_conversations_returns() {
2203         return new external_single_structure(
2204             array(
2205                 'contacts' => new external_multiple_structure(
2206                     self::get_messagearea_contact_structure()
2207                 )
2208             )
2209         );
2210     }
2212     /**
2213      * Marking the method as deprecated.
2214      *
2215      * @return bool
2216      */
2217     public static function data_for_messagearea_conversations_is_deprecated() {
2218         return true;
2219     }
2221     /**
2222      * The messagearea contacts return parameters.
2223      *
2224      * @deprecated since 3.6
2225      * @return external_function_parameters
2226      * @since 3.2
2227      */
2228     public static function data_for_messagearea_contacts_parameters() {
2229         return self::data_for_messagearea_conversations_parameters();
2230     }
2232     /**
2233      * Get messagearea contacts parameters.
2234      *
2235      * @deprecated since 3.6
2236      * @param int $userid The id of the user who we are viewing conversations for
2237      * @param int $limitfrom
2238      * @param int $limitnum
2239      * @return stdClass
2240      * @throws moodle_exception
2241      * @since 3.2
2242      */
2243     public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
2244         global $CFG, $PAGE, $USER;
2246         // Check if messaging is enabled.
2247         if (empty($CFG->messaging)) {
2248             throw new moodle_exception('disabled', 'message');
2249         }
2251         $systemcontext = context_system::instance();
2253         $params = array(
2254             'userid' => $userid,
2255             'limitfrom' => $limitfrom,
2256             'limitnum' => $limitnum
2257         );
2258         $params = self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
2259         self::validate_context($systemcontext);
2261         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2262             throw new moodle_exception('You do not have permission to perform this action.');
2263         }
2265         $contacts = \core_message\api::get_contacts($params['userid'], $params['limitfrom'], $params['limitnum']);
2266         $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
2268         $renderer = $PAGE->get_renderer('core_message');
2269         return $contacts->export_for_template($renderer);
2270     }
2272     /**
2273      * The messagearea contacts return structure.
2274      *
2275      * @deprecated since 3.6
2276      * @return external_single_structure
2277      * @since 3.2
2278      */
2279     public static function data_for_messagearea_contacts_returns() {
2280         return self::data_for_messagearea_conversations_returns();
2281     }
2283     /**
2284      * Marking the method as deprecated.
2285      *
2286      * @return bool
2287      */
2288     public static function data_for_messagearea_contacts_is_deprecated() {
2289         return true;
2290     }
2292     /**
2293      * The messagearea messages parameters.
2294      *
2295      * @deprecated since 3.6
2296      * @return external_function_parameters
2297      * @since 3.2
2298      */
2299     public static function data_for_messagearea_messages_parameters() {
2300         return new external_function_parameters(
2301             array(
2302                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2303                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2304                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2305                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
2306                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
2307                 'timefrom' => new external_value(PARAM_INT,
2308                     'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
2309             )
2310         );
2311     }
2313     /**
2314      * Get messagearea messages.
2315      *
2316      * @deprecated since 3.6
2317      * @param int $currentuserid The current user's id
2318      * @param int $otheruserid The other user's id
2319      * @param int $limitfrom
2320      * @param int $limitnum
2321      * @param boolean $newest
2322      * @return stdClass
2323      * @throws moodle_exception
2324      * @since 3.2
2325      */
2326     public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
2327                                                          $newest = false, $timefrom = 0) {
2328         global $CFG, $PAGE, $USER;
2330         // Check if messaging is enabled.
2331         if (empty($CFG->messaging)) {
2332             throw new moodle_exception('disabled', 'message');
2333         }
2335         $systemcontext = context_system::instance();
2337         $params = array(
2338             'currentuserid' => $currentuserid,
2339             'otheruserid' => $otheruserid,
2340             'limitfrom' => $limitfrom,
2341             'limitnum' => $limitnum,
2342             'newest' => $newest,
2343             'timefrom' => $timefrom,
2344         );
2345         $params = self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
2346         self::validate_context($systemcontext);
2348         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2349             throw new moodle_exception('You do not have permission to perform this action.');
2350         }
2352         if ($params['newest']) {
2353             $sort = 'timecreated DESC';
2354         } else {
2355             $sort = 'timecreated ASC';
2356         }
2358         // We need to enforce a one second delay on messages to avoid race conditions of current
2359         // messages still being sent.
2360         //
2361         // There is a chance that we could request messages before the current time's
2362         // second has elapsed and while other messages are being sent in that same second. In which
2363         // case those messages will be lost.
2364         //
2365         // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
2366         if (!empty($params['timefrom'])) {
2367             $timeto = time() - 1;
2368         } else {
2369             $timeto = 0;
2370         }
2372         // No requesting messages from the current time, as stated above.
2373         if ($params['timefrom'] == time()) {
2374             $messages = [];
2375         } else {
2376             $messages = \core_message\api::get_messages($params['currentuserid'], $params['otheruserid'], $params['limitfrom'],
2377                                                         $params['limitnum'], $sort, $params['timefrom'], $timeto);
2378         }
2380         $messages = new \core_message\output\messagearea\messages($params['currentuserid'], $params['otheruserid'], $messages);
2382         $renderer = $PAGE->get_renderer('core_message');
2383         return $messages->export_for_template($renderer);
2384     }
2386     /**
2387      * The messagearea messages return structure.
2388      *
2389      * @deprecated since 3.6
2390      * @return external_single_structure
2391      * @since 3.2
2392      */
2393     public static function data_for_messagearea_messages_returns() {
2394         return new external_single_structure(
2395             array(
2396                 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
2397                     the messages on behalf of?'),
2398                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2399                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2400                 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
2401                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2402                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2403                 'messages' => new external_multiple_structure(
2404                     self::get_messagearea_message_structure()
2405                 ),
2406                 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
2407             )
2408         );
2409     }
2411     /**
2412      * Marking the method as deprecated.
2413      *
2414      * @return bool
2415      */
2416     public static function data_for_messagearea_messages_is_deprecated() {
2417         return true;
2418     }
2420     /**
2421      * The conversation messages parameters.
2422      *
2423      * @return external_function_parameters
2424      * @since 3.6
2425      */
2426     public static function get_conversation_messages_parameters() {
2427         return new external_function_parameters(
2428             array(
2429                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2430                 'convid' => new external_value(PARAM_INT, 'The conversation id'),
2431                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2432                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
2433                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
2434                 'timefrom' => new external_value(PARAM_INT,
2435                     'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
2436             )
2437         );
2438     }
2440     /**
2441      * Get conversation messages.
2442      *
2443      * @param  int $currentuserid The current user's id.
2444      * @param  int $convid The conversation id.
2445      * @param  int $limitfrom Return a subset of records, starting at this point (optional).
2446      * @param  int $limitnum Return a subset comprising this many records in total (optional, required if $limitfrom is set).
2447      * @param  bool $newest True for getting first newest messages, false otherwise.
2448      * @param  int  $timefrom The time from the conversation messages to get.
2449      * @return stdClass The messages and members who have sent some of these messages.
2450      * @throws moodle_exception
2451      * @since 3.6
2452      */
2453     public static function get_conversation_messages(int $currentuserid, int $convid, int $limitfrom = 0, int $limitnum = 0,
2454                                                          bool $newest = false, int $timefrom = 0) {
2455         global $CFG, $PAGE, $USER;
2457         // Check if messaging is enabled.
2458         if (empty($CFG->messaging)) {
2459             throw new moodle_exception('disabled', 'message');
2460         }
2462         $systemcontext = context_system::instance();
2464         $params = array(
2465             'currentuserid' => $currentuserid,
2466             'convid' => $convid,
2467             'limitfrom' => $limitfrom,
2468             'limitnum' => $limitnum,
2469             'newest' => $newest,
2470             'timefrom' => $timefrom,
2471         );
2472         $params = self::validate_parameters(self::get_conversation_messages_parameters(), $params);
2473         self::validate_context($systemcontext);
2475         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2476             throw new moodle_exception('You do not have permission to perform this action.');
2477         }
2479         $sort = $newest ? 'timecreated DESC' : 'timecreated ASC';
2481         // We need to enforce a one second delay on messages to avoid race conditions of current
2482         // messages still being sent.
2483         //
2484         // There is a chance that we could request messages before the current time's
2485         // second has elapsed and while other messages are being sent in that same second. In which
2486         // case those messages will be lost.
2487         //
2488         // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
2489         $timeto = empty($params['timefrom']) ? 0 : time() - 1;
2491         // No requesting messages from the current time, as stated above.
2492         if ($params['timefrom'] == time()) {
2493             $messages = [];
2494         } else {
2495             $messages = \core_message\api::get_conversation_messages(
2496                 $params['currentuserid'],
2497                 $params['convid'],
2498                 $params['limitfrom'],
2499                 $params['limitnum'],
2500                 $sort,
2501                 $params['timefrom'],
2502                 $timeto);
2503         }
2505         return $messages;
2506     }
2508     /**
2509      * The messagearea messages return structure.
2510      *
2511      * @return external_single_structure
2512      * @since 3.6
2513      */
2514     public static function get_conversation_messages_returns() {
2515         return new external_single_structure(
2516             array(
2517                 'id' => new external_value(PARAM_INT, 'The conversation id'),
2518                 'members' => new external_multiple_structure(
2519                     self::get_conversation_member_structure()
2520                 ),
2521                 'messages' => new external_multiple_structure(
2522                     self::get_conversation_message_structure()
2523                 ),
2524             )
2525         );
2526     }
2528     /**
2529      * The user contacts return parameters.
2530      *
2531      * @return external_function_parameters
2532      */
2533     public static function get_user_contacts_parameters() {
2534         return new external_function_parameters(
2535             array(
2536                 'userid' => new external_value(PARAM_INT, 'The id of the user who we retrieving the contacts for'),
2537                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
2538                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
2539             )
2540         );
2541     }
2543     /**
2544      * Get user contacts.
2545      *
2546      * @param int $userid The id of the user who we are viewing conversations for
2547      * @param int $limitfrom
2548      * @param int $limitnum
2549      * @return array
2550      * @throws moodle_exception
2551      */
2552     public static function get_user_contacts(int $userid, int $limitfrom = 0, int $limitnum = 0) {
2553         global $CFG, $USER;
2555         // Check if messaging is enabled.
2556         if (empty($CFG->messaging)) {
2557             throw new moodle_exception('disabled', 'message');
2558         }
2560         $systemcontext = context_system::instance();
2562         $params = array(
2563             'userid' => $userid,
2564             'limitfrom' => $limitfrom,
2565             'limitnum' => $limitnum
2566         );
2567         $params = self::validate_parameters(self::get_user_contacts_parameters(), $params);
2568         self::validate_context($systemcontext);
2570         if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2571             throw new moodle_exception('You do not have permission to perform this action.');
2572         }
2574         return \core_message\api::get_user_contacts($params['userid'], $params['limitfrom'], $params['limitnum']);
2575     }
2577     /**
2578      * The user contacts return structure.
2579      *
2580      * @return external_multiple_structure
2581      */
2582     public static function get_user_contacts_returns() {
2583         return new external_multiple_structure(
2584             self::get_conversation_member_structure()
2585         );
2586     }
2588     /**
2589      * The get most recent message return parameters.
2590      *
2591      * @deprecated since 3.6
2592      * @return external_function_parameters
2593      * @since 3.2
2594      */
2595     public static function data_for_messagearea_get_most_recent_message_parameters() {
2596         return new external_function_parameters(
2597             array(
2598                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2599                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
2600             )
2601         );
2602     }
2604     /**
2605      * Get the most recent message in a conversation.
2606      *
2607      * @deprecated since 3.6
2608      * @param int $currentuserid The current user's id
2609      * @param int $otheruserid The other user's id
2610      * @return stdClass
2611      * @throws moodle_exception
2612      * @since 3.2
2613      */
2614     public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
2615         global $CFG, $PAGE, $USER;
2617         // Check if messaging is enabled.
2618         if (empty($CFG->messaging)) {
2619             throw new moodle_exception('disabled', 'message');
2620         }
2622         $systemcontext = context_system::instance();
2624         $params = array(
2625             'currentuserid' => $currentuserid,
2626             'otheruserid' => $otheruserid
2627         );
2628         $params = self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
2629         self::validate_context($systemcontext);
2631         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2632             throw new moodle_exception('You do not have permission to perform this action.');
2633         }
2635         $message = \core_message\api::get_most_recent_message($params['currentuserid'], $params['otheruserid']);
2636         $message = new \core_message\output\messagearea\message($message);
2638         $renderer = $PAGE->get_renderer('core_message');
2639         return $message->export_for_template($renderer);
2640     }
2642     /**
2643      * The get most recent message return structure.
2644      *
2645      * @deprecated since 3.6
2646      * @return external_single_structure
2647      * @since 3.2
2648      */
2649     public static function data_for_messagearea_get_most_recent_message_returns() {
2650         return self::get_messagearea_message_structure();
2651     }
2653     /**
2654      * Marking the method as deprecated.
2655      *
2656      * @return bool
2657      */
2658     public static function data_for_messagearea_get_most_recent_message_is_deprecated() {
2659         return true;
2660     }
2662     /**
2663      * The get profile parameters.
2664      *
2665      * @deprecated since 3.6
2666      * @return external_function_parameters
2667      * @since 3.2
2668      */
2669     public static function data_for_messagearea_get_profile_parameters() {
2670         return new external_function_parameters(
2671             array(
2672                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
2673                 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
2674             )
2675         );
2676     }
2678     /**
2679      * Get the profile information for a contact.
2680      *
2681      * @deprecated since 3.6
2682      * @param int $currentuserid The current user's id
2683      * @param int $otheruserid The id of the user whose profile we are viewing
2684      * @return stdClass
2685      * @throws moodle_exception
2686      * @since 3.2
2687      */
2688     public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
2689         global $CFG, $PAGE, $USER;
2691         // Check if messaging is enabled.
2692         if (empty($CFG->messaging)) {
2693             throw new moodle_exception('disabled', 'message');
2694         }
2696         $systemcontext = context_system::instance();
2698         $params = array(
2699             'currentuserid' => $currentuserid,
2700             'otheruserid' => $otheruserid
2701         );
2702         $params = self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
2703         self::validate_context($systemcontext);
2705         if (($USER->id != $params['currentuserid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
2706             throw new moodle_exception('You do not have permission to perform this action.');
2707         }
2709         $profile = \core_message\api::get_profile($params['currentuserid'], $params['otheruserid']);
2710         $profile = new \core_message\output\messagearea\profile($profile);
2712         $renderer = $PAGE->get_renderer('core_message');
2713         return $profile->export_for_template($renderer);
2714     }
2716     /**
2717      * The get profile return structure.
2718      *
2719      * @deprecated since 3.6
2720      * @return external_single_structure
2721      * @since 3.2
2722      */
2723     public static function data_for_messagearea_get_profile_returns() {
2724         return new external_single_structure(
2725             array(
2726                 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
2727                 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
2728                 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
2729                 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
2730                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
2731                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
2732                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
2733                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
2734                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
2735                 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
2736                 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
2737             )
2738         );
2739     }
2741     /**
2742      * Marking the method as deprecated.
2743      *
2744      * @return bool
2745      */
2746     public static function data_for_messagearea_get_profile_is_deprecated() {
2747         return true;
2748     }
2750     /**
2751      * Get contacts parameters description.
2752      *
2753      * @deprecated since 3.6
2754      * @return external_function_parameters
2755      * @since Moodle 2.5
2756      */
2757     public static function get_contacts_parameters() {
2758         return new external_function_parameters(array());
2759     }
2761     /**
2762      * Get contacts.
2763      *
2764      * @deprecated since 3.6
2765      * @return external_description
2766      * @since Moodle 2.5
2767      */
2768     public static function get_contacts() {
2769         global $CFG, $PAGE, $USER;
2771         // Check if messaging is enabled.
2772         if (empty($CFG->messaging)) {
2773             throw new moodle_exception('disabled', 'message');
2774         }
2776         require_once($CFG->dirroot . '/user/lib.php');
2778         $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
2779         $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
2780         foreach ($contacts as $contact) {
2781             // Set the mode.
2782             $mode = 'offline';
2783             if (\core_message\helper::is_online($contact->lastaccess)) {
2784                 $mode = 'online';
2785             }
2787             $newcontact = array(
2788                 'id' => $contact->id,
2789                 'fullname' => fullname($contact),
2790                 'unread' => $contact->messagecount
2791             );
2793             $userpicture = new user_picture($contact);
2794             $userpicture->size = 1; // Size f1.
2795             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2796             $userpicture->size = 0; // Size f2.
2797             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2799             $allcontacts[$mode][$contact->id] = $newcontact;
2800         }
2802         $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
2803         foreach ($strangers as $contact) {
2804             $newcontact = array(
2805                 'id' => $contact->id,
2806                 'fullname' => fullname($contact),
2807                 'unread' => $contact->messagecount
2808             );
2810             $userpicture = new user_picture($contact);
2811             $userpicture->size = 1; // Size f1.
2812             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2813             $userpicture->size = 0; // Size f2.
2814             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2816             $allcontacts['strangers'][$contact->id] = $newcontact;
2817         }
2819         // Add noreply user and support user to the list, if they don't exist.
2820         $supportuser = core_user::get_support_user();
2821         if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
2822             $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
2823             if ($supportuser->messagecount > 0) {
2824                 $supportuser->fullname = fullname($supportuser);
2825                 $supportuser->unread = $supportuser->messagecount;
2826                 $allcontacts['strangers'][$supportuser->id] = $supportuser;
2827             }
2828         }
2830         $noreplyuser = core_user::get_noreply_user();
2831         if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
2832             $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
2833             if ($noreplyuser->messagecount > 0) {
2834                 $noreplyuser->fullname = fullname($noreplyuser);
2835                 $noreplyuser->unread = $noreplyuser->messagecount;
2836                 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
2837             }
2838         }
2840         return $allcontacts;
2841     }
2843     /**
2844      * Get contacts return description.
2845      *
2846      * @deprecated since 3.6
2847      * @return external_description
2848      * @since Moodle 2.5
2849      */
2850     public static function get_contacts_returns() {
2851         return new external_single_structure(
2852             array(
2853                 'online' => new external_multiple_structure(
2854                     new external_single_structure(
2855                         array(
2856                             'id' => new external_value(PARAM_INT, 'User ID'),
2857                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2858                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2859                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2860                             'unread' => new external_value(PARAM_INT, 'Unread message count')
2861                         )
2862                     ),
2863                     'List of online contacts'
2864                 ),
2865                 'offline' => new external_multiple_structure(
2866                     new external_single_structure(
2867                         array(
2868                             'id' => new external_value(PARAM_INT, 'User ID'),
2869                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2870                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2871                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2872                             'unread' => new external_value(PARAM_INT, 'Unread message count')
2873                         )
2874                     ),
2875                     'List of offline contacts'
2876                 ),
2877                 'strangers' => new external_multiple_structure(
2878                     new external_single_structure(
2879                         array(
2880                             'id' => new external_value(PARAM_INT, 'User ID'),
2881                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2882                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2883                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
2884                             'unread' => new external_value(PARAM_INT, 'Unread message count')
2885                         )
2886                     ),
2887                     'List of users that are not in the user\'s contact list but have sent a message'
2888                 )
2889             )
2890         );
2891     }
2893     /**
2894      * Marking the method as deprecated.
2895      *
2896      * @return bool
2897      */
2898     public static function get_contacts_is_deprecated() {
2899         return true;
2900     }
2902     /**
2903      * Search contacts parameters description.
2904      *
2905      * @return external_function_parameters
2906      * @since Moodle 2.5
2907      */
2908     public static function search_contacts_parameters() {
2909         return new external_function_parameters(
2910             array(
2911                 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
2912                 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
2913                     VALUE_DEFAULT, false)
2914             )
2915         );
2916     }
2918     /**
2919      * Search contacts.
2920      *
2921      * @param string $searchtext query string.
2922      * @param bool $onlymycourses limit the search to the user's courses only.
2923      * @return external_description
2924      * @since Moodle 2.5
2925      */
2926     public static function search_contacts($searchtext, $onlymycourses = false) {
2927         global $CFG, $USER, $PAGE;
2928         require_once($CFG->dirroot . '/user/lib.php');
2930         // Check if messaging is enabled.
2931         if (empty($CFG->messaging)) {
2932             throw new moodle_exception('disabled', 'message');
2933         }
2935         require_once($CFG->libdir . '/enrollib.php');
2937         $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
2938         $params = self::validate_parameters(self::search_contacts_parameters(), $params);
2940         // Extra validation, we do not allow empty queries.
2941         if ($params['searchtext'] === '') {
2942             throw new moodle_exception('querystringcannotbeempty');
2943         }
2945         $courseids = array();
2946         if ($params['onlymycourses']) {
2947             $mycourses = enrol_get_my_courses(array('id'));
2948             foreach ($mycourses as $mycourse) {
2949                 $courseids[] = $mycourse->id;
2950             }
2951         } else {
2952             $courseids[] = SITEID;
2953         }
2955         // Retrieving the users matching the query.
2956         $users = message_search_users($courseids, $params['searchtext']);
2957         $results = array();
2958         foreach ($users as $user) {
2959             $results[$user->id] = $user;
2960         }
2962         // Reorganising information.
2963         foreach ($results as &$user) {
2964             $newuser = array(
2965                 'id' => $user->id,
2966                 'fullname' => fullname($user)
2967             );
2969             // Avoid undefined property notice as phone not specified.
2970             $user->phone1 = null;
2971             $user->phone2 = null;
2973             $userpicture = new user_picture($user);
2974             $userpicture->size = 1; // Size f1.
2975             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2976             $userpicture->size = 0; // Size f2.
2977             $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
2979             $user = $newuser;
2980         }
2982         return $results;
2983     }
2985     /**
2986      * Search contacts return description.
2987      *
2988      * @return external_description
2989      * @since Moodle 2.5
2990      */
2991     public static function search_contacts_returns() {
2992         return new external_multiple_structure(
2993             new external_single_structure(
2994                 array(
2995                     'id' => new external_value(PARAM_INT, 'User ID'),
2996                     'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2997                     'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
2998                     'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
2999                 )
3000             ),
3001             'List of contacts'
3002         );
3003     }
3005     /**
3006      * Get messages parameters description.
3007      *
3008      * @return external_function_parameters
3009      * @since 2.8
3010      */
3011     public static function get_messages_parameters() {
3012         return new external_function_parameters(
3013             array(
3014                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3015                 'useridfrom' => new external_value(
3016                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3017                     VALUE_DEFAULT, 0),
3018                 'type' => new external_value(
3019                     PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
3020                     VALUE_DEFAULT, 'both'),
3021                 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
3022                 'newestfirst' => new external_value(
3023                     PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
3024                     VALUE_DEFAULT, true),
3025                 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
3026                 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
3027             )
3028         );
3029     }
3031     /**
3032      * Get messages function implementation.
3033      *
3034      * @since  2.8
3035      * @throws invalid_parameter_exception
3036      * @throws moodle_exception
3037      * @param  int      $useridto       the user id who received the message
3038      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
3039      * @param  string   $type           type of message to return, expected values: notifications, conversations and both
3040      * @param  bool     $read           true for retreiving read messages, false for unread
3041      * @param  bool     $newestfirst    true for ordering by newest first, false for oldest first
3042      * @param  int      $limitfrom      limit from
3043      * @param  int      $limitnum       limit num
3044      * @return external_description
3045      */
3046     public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
3047                                         $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
3048         global $CFG, $USER;
3050         $warnings = array();
3052         $params = array(
3053             'useridto' => $useridto,
3054             'useridfrom' => $useridfrom,
3055             'type' => $type,
3056             'read' => $read,
3057             'newestfirst' => $newestfirst,
3058             'limitfrom' => $limitfrom,
3059             'limitnum' => $limitnum
3060         );
3062         $params = self::validate_parameters(self::get_messages_parameters(), $params);
3064         $context = context_system::instance();
3065         self::validate_context($context);
3067         $useridto = $params['useridto'];
3068         $useridfrom = $params['useridfrom'];
3069         $type = $params['type'];
3070         $read = $params['read'];
3071         $newestfirst = $params['newestfirst'];
3072         $limitfrom = $params['limitfrom'];
3073         $limitnum = $params['limitnum'];
3075         $allowedvalues = array('notifications', 'conversations', 'both');
3076         if (!in_array($type, $allowedvalues)) {
3077             throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
3078                 'allowed values are: ' . implode(',', $allowedvalues));
3079         }
3081         // Check if private messaging between users is allowed.
3082         if (empty($CFG->messaging)) {
3083             // If we are retreiving only conversations, and messaging is disabled, throw an exception.
3084             if ($type == "conversations") {
3085                 throw new moodle_exception('disabled', 'message');
3086             }
3087             if ($type == "both") {
3088                 $warning = array();
3089                 $warning['item'] = 'message';
3090                 $warning['itemid'] = $USER->id;
3091                 $warning['warningcode'] = '1';
3092                 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
3093                     Only notifications will be returned';
3094                 $warnings[] = $warning;
3095             }
3096         }
3098         if (!empty($useridto)) {
3099             if (core_user::is_real_user($useridto)) {
3100                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3101             } else {
3102                 throw new moodle_exception('invaliduser');
3103             }
3104         }
3106         if (!empty($useridfrom)) {
3107             // We use get_user here because the from user can be the noreply or support user.
3108             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3109         }
3111         // Check if the current user is the sender/receiver or just a privileged user.
3112         if ($useridto != $USER->id and $useridfrom != $USER->id and
3113              !has_capability('moodle/site:readallmessages', $context)) {
3114             throw new moodle_exception('accessdenied', 'admin');
3115         }
3117         // Which type of messages to retrieve.
3118         $notifications = -1;
3119         if ($type != 'both') {
3120             $notifications = ($type == 'notifications') ? 1 : 0;
3121         }
3123         $orderdirection = $newestfirst ? 'DESC' : 'ASC';
3124         $sort = "mr.timecreated $orderdirection";
3126         if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
3127             $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
3129             // In some cases, we don't need to get the to/from user objects from the sql query.
3130             $userfromfullname = '';
3131             $usertofullname = '';
3133             // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
3134             if (!empty($useridto)) {
3135                 $usertofullname = fullname($userto, $canviewfullname);
3136                 // The user from may or may not be filled.
3137                 if (!empty($useridfrom)) {
3138                     $userfromfullname = fullname($userfrom, $canviewfullname);
3139                 }
3140             } else {
3141                 // If the useridto field is empty, the useridfrom must be filled.
3142                 $userfromfullname = fullname($userfrom, $canviewfullname);
3143             }
3144             foreach ($messages as $mid => $message) {
3146                 // Do not return deleted messages.
3147                 if (!$message->notification) {
3148                     if (($useridto == $USER->id and $message->timeusertodeleted) or
3149                         ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
3150                         unset($messages[$mid]);
3151                         continue;
3152                     }
3153                 }
3155                 // We need to get the user from the query.
3156                 if (empty($userfromfullname)) {
3157                     // Check for non-reply and support users.
3158                     if (core_user::is_real_user($message->useridfrom)) {
3159                         $user = new stdClass();
3160                         $user = username_load_fields_from_object($user, $message, 'userfrom');
3161                         $message->userfromfullname = fullname($user, $canviewfullname);
3162                     } else {
3163                         $user = core_user::get_user($message->useridfrom);
3164                         $message->userfromfullname = fullname($user, $canviewfullname);
3165                     }
3166                 } else {
3167                     $message->userfromfullname = $userfromfullname;
3168                 }
3170                 // We need to get the user from the query.
3171                 if (empty($usertofullname)) {
3172                     $user = new stdClass();
3173                     $user = username_load_fields_from_object($user, $message, 'userto');
3174                     $message->usertofullname = fullname($user, $canviewfullname);
3175                 } else {
3176                     $message->usertofullname = $usertofullname;
3177                 }
3179                 $message->text = message_format_message_text($message);
3180                 $messages[$mid] = (array) $message;
3181             }
3182         }
3184         $results = array(
3185             'messages' => $messages,
3186             'warnings' => $warnings
3187         );
3189         return $results;
3190     }
3192     /**
3193      * Get messages return description.
3194      *
3195      * @return external_single_structure
3196      * @since 2.8
3197      */
3198     public static function get_messages_returns() {
3199         return new external_single_structure(
3200             array(
3201                 'messages' => new external_multiple_structure(
3202                     new external_single_structure(
3203                         array(
3204                             'id' => new external_value(PARAM_INT, 'Message id'),
3205                             'useridfrom' => new external_value(PARAM_INT, 'User from id'),
3206                             'useridto' => new external_value(PARAM_INT, 'User to id'),
3207                             'subject' => new external_value(PARAM_TEXT, 'The message subject'),
3208                             'text' => new external_value(PARAM_RAW, 'The message text formated'),
3209                             'fullmessage' => new external_value(PARAM_RAW, 'The message'),
3210                             'fullmessageformat' => new external_format_value('fullmessage'),
3211                             'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
3212                             'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
3213                             'notification' => new external_value(PARAM_INT, 'Is a notification?'),
3214                             'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
3215                             'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
3216                             'timecreated' => new external_value(PARAM_INT, 'Time created'),
3217                             'timeread' => new external_value(PARAM_INT, 'Time read'),
3218                             'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
3219                             'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name'),
3220                             'component' => new external_value(PARAM_TEXT, 'The component that generated the notification',
3221                                 VALUE_OPTIONAL),
3222                             'eventtype' => new external_value(PARAM_TEXT, 'The type of notification', VALUE_OPTIONAL),
3223                             'customdata' => new external_value(PARAM_RAW, 'Custom data to be passed to the message processor.
3224                                 The data here is serialised using json_encode().', VALUE_OPTIONAL),
3225                         ), 'message'
3226                     )
3227                 ),
3228                 'warnings' => new external_warnings()
3229             )
3230         );
3231     }
3233     /**
3234      * Mark all notifications as read parameters description.
3235      *
3236      * @return external_function_parameters
3237      * @since 3.2
3238      */
3239     public static function mark_all_notifications_as_read_parameters() {
3240         return new external_function_parameters(
3241             array(
3242                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3243                 'useridfrom' => new external_value(
3244                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
3245                     VALUE_DEFAULT, 0),
3246             )
3247         );
3248     }
3250     /**
3251      * Mark all notifications as read function.
3252      *
3253      * @since  3.2
3254      * @throws invalid_parameter_exception
3255      * @throws moodle_exception
3256      * @param  int      $useridto       the user id who received the message
3257      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
3258      * @return external_description
3259      */
3260     public static function mark_all_notifications_as_read($useridto, $useridfrom) {
3261         global $USER;
3263         $params = self::validate_parameters(
3264             self::mark_all_notifications_as_read_parameters(),
3265             array(
3266                 'useridto' => $useridto,
3267                 'useridfrom' => $useridfrom,
3268             )
3269         );
3271         $context = context_system::instance();
3272         self::validate_context($context);
3274         $useridto = $params['useridto'];
3275         $useridfrom = $params['useridfrom'];
3277         if (!empty($useridto)) {
3278             if (core_user::is_real_user($useridto)) {
3279                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3280             } else {
3281                 throw new moodle_exception('invaliduser');
3282             }
3283         }
3285         if (!empty($useridfrom)) {
3286             // We use get_user here because the from user can be the noreply or support user.
3287             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
3288         }
3290         // Check if the current user is the sender/receiver or just a privileged user.
3291         if ($useridto != $USER->id and $useridfrom != $USER->id and
3292             // The deleteanymessage cap seems more reasonable here than readallmessages.
3293              !has_capability('moodle/site:deleteanymessage', $context)) {
3294             throw new moodle_exception('accessdenied', 'admin');
3295         }
3297         \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
3299         return true;
3300     }
3302     /**
3303      * Mark all notifications as read return description.
3304      *
3305      * @return external_single_structure
3306      * @since 3.2
3307      */
3308     public static function mark_all_notifications_as_read_returns() {
3309         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
3310     }
3312     /**
3313      * Get unread conversations count parameters description.
3314      *
3315      * @return external_function_parameters
3316      * @since 3.2
3317      */
3318     public static function get_unread_conversations_count_parameters() {
3319         return new external_function_parameters(
3320             array(
3321                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
3322             )
3323         );
3324     }
3326     /**
3327      * Get unread messages count function.
3328      *
3329      * @since  3.2
3330      * @throws invalid_parameter_exception
3331      * @throws moodle_exception
3332      * @param  int      $useridto       the user id who received the message
3333      * @return external_description
3334      */
3335     public static function get_unread_conversations_count($useridto) {
3336         global $USER, $CFG;
3338         // Check if messaging is enabled.
3339         if (empty($CFG->messaging)) {
3340             throw new moodle_exception('disabled', 'message');
3341         }
3343         $params = self::validate_parameters(
3344             self::get_unread_conversations_count_parameters(),
3345             array('useridto' => $useridto)
3346         );
3348         $context = context_system::instance();
3349         self::validate_context($context);
3351         $useridto = $params['useridto'];
3353         if (!empty($useridto)) {
3354             if (core_user::is_real_user($useridto)) {
3355                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
3356             } else {
3357                 throw new moodle_exception('invaliduser');
3358             }
3359         } else {
3360             $useridto = $USER->id;
3361         }
3363         // Check if the current user is the receiver or just a privileged user.
3364         if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
3365             throw new moodle_exception('accessdenied', 'admin');
3366         }
3368         return \core_message\api::count_unread_conversations($userto);
3369     }
3371     /**
3372      * Get unread conversations count return description.
3373      *
3374      * @return external_single_structure
3375      * @since 3.2
3376      */
3377     public static function get_unread_conversations_count_returns() {
3378         return new external_value(PARAM_INT, 'The count of unread messages for the user');
3379     }
3381     /**
3382      * Get blocked users parameters description.
3383      *
3384      * @return external_function_parameters
3385      * @since 2.9
3386      */
3387     public static function get_blocked_users_parameters() {
3388         return new external_function_parameters(
3389             array(
3390                 'userid' => new external_value(PARAM_INT,
3391                                 'the user whose blocked users we want to retrieve',
3392                                 VALUE_REQUIRED),
3393             )
3394         );
3395     }
3397     /**
3398      * Retrieve a list of users blocked
3399      *
3400