MDL-63211 core_message: added new web services
[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 {
43     /**
44      * Returns description of method parameters
45      *
46      * @return external_function_parameters
47      * @since Moodle 2.2
48      */
49     public static function send_instant_messages_parameters() {
50         return new external_function_parameters(
51             array(
52                 'messages' => new external_multiple_structure(
53                     new external_single_structure(
54                         array(
55                             'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
56                             'text' => new external_value(PARAM_RAW, 'the text of the message'),
57                             'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
58                             'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own client id for the message. If this id is provided, the fail message id will be returned to you', VALUE_OPTIONAL),
59                         )
60                     )
61                 )
62             )
63         );
64     }
66     /**
67      * Send private messages from the current USER to other users
68      *
69      * @param array $messages An array of message to send.
70      * @return array
71      * @since Moodle 2.2
72      */
73     public static function send_instant_messages($messages = array()) {
74         global $CFG, $USER, $DB;
76         // Check if messaging is enabled.
77         if (empty($CFG->messaging)) {
78             throw new moodle_exception('disabled', 'message');
79         }
81         // Ensure the current user is allowed to run this function
82         $context = context_system::instance();
83         self::validate_context($context);
84         require_capability('moodle/site:sendmessage', $context);
86         $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
88         //retrieve all tousers of the messages
89         $receivers = array();
90         foreach($params['messages'] as $message) {
91             $receivers[] = $message['touserid'];
92         }
93         list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers, SQL_PARAMS_NAMED, 'userid_');
94         $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
95         $blocklist   = array();
96         $contactlist = array();
97         $sqlparams['contactid'] = $USER->id;
98         $rs = $DB->get_recordset_sql("SELECT *
99                                         FROM {message_contacts}
100                                        WHERE userid $sqluserids
101                                              AND contactid = :contactid", $sqlparams);
102         foreach ($rs as $record) {
103             if ($record->blocked) {
104                 // $record->userid is blocking current user
105                 $blocklist[$record->userid] = true;
106             } else {
107                 // $record->userid have current user as contact
108                 $contactlist[$record->userid] = true;
109             }
110         }
111         $rs->close();
113         $canreadallmessages = has_capability('moodle/site:readallmessages', $context);
115         $resultmessages = array();
116         foreach ($params['messages'] as $message) {
117             $resultmsg = array(); //the infos about the success of the operation
119             //we are going to do some checking
120             //code should match /messages/index.php checks
121             $success = true;
123             //check the user exists
124             if (empty($tousers[$message['touserid']])) {
125                 $success = false;
126                 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
127             }
129             //check that the touser is not blocking the current user
130             if ($success and !empty($blocklist[$message['touserid']]) and !$canreadallmessages) {
131                 $success = false;
132                 $errormessage = get_string('userisblockingyou', 'message');
133             }
135             // Check if the user is a contact
136             //TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
137             $blocknoncontacts = get_user_preferences('message_blocknoncontacts', NULL, $message['touserid']);
138             // message_blocknoncontacts option is on and current user is not in contact list
139             if ($success && empty($contactlist[$message['touserid']]) && !empty($blocknoncontacts)) {
140                 // The user isn't a contact and they have selected to block non contacts so this message won't be sent.
141                 $success = false;
142                 $errormessage = get_string('userisblockingyounoncontact', 'message',
143                         fullname(core_user::get_user($message['touserid'])));
144             }
146             //now we can send the message (at least try)
147             if ($success) {
148                 //TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object
149                 $success = message_post_message($USER, $tousers[$message['touserid']],
150                         $message['text'], external_validate_format($message['textformat']));
151             }
153             //build the resultmsg
154             if (isset($message['clientmsgid'])) {
155                 $resultmsg['clientmsgid'] = $message['clientmsgid'];
156             }
157             if ($success) {
158                 $resultmsg['msgid'] = $success;
159             } else {
160                 // WARNINGS: for backward compatibility we return this errormessage.
161                 //          We should have thrown exceptions as these errors prevent results to be returned.
162                 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
163                 $resultmsg['msgid'] = -1;
164                 $resultmsg['errormessage'] = $errormessage;
165             }
167             $resultmessages[] = $resultmsg;
168         }
170         return $resultmessages;
171     }
173     /**
174      * Returns description of method result value
175      *
176      * @return external_description
177      * @since Moodle 2.2
178      */
179     public static function send_instant_messages_returns() {
180         return new external_multiple_structure(
181             new external_single_structure(
182                 array(
183                     'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds:  id of the created message if it succeeded, -1 when failed'),
184                     'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
185                     'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL)
186                 )
187             )
188         );
189     }
191     /**
192      * Create contacts parameters description.
193      *
194      * @deprecated since Moodle 3.6
195      * @return external_function_parameters
196      * @since Moodle 2.5
197      */
198     public static function create_contacts_parameters() {
199         return new external_function_parameters(
200             array(
201                 'userids' => new external_multiple_structure(
202                     new external_value(PARAM_INT, 'User ID'),
203                     'List of user IDs'
204                 ),
205                 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
206                     current user', VALUE_DEFAULT, 0)
207             )
208         );
209     }
211     /**
212      * Create contacts.
213      *
214      * @deprecated since Moodle 3.6
215      * @param array $userids array of user IDs.
216      * @param int $userid The id of the user we are creating the contacts for
217      * @return external_description
218      * @since Moodle 2.5
219      */
220     public static function create_contacts($userids, $userid = 0) {
221         global $CFG, $USER;
223         // Check if messaging is enabled.
224         if (empty($CFG->messaging)) {
225             throw new moodle_exception('disabled', 'message');
226         }
228         if (empty($userid)) {
229             $userid = $USER->id;
230         }
232         // Validate context.
233         $context = context_system::instance();
234         self::validate_context($context);
236         $capability = 'moodle/site:manageallmessaging';
237         if (($USER->id != $userid) && !has_capability($capability, $context)) {
238             throw new required_capability_exception($context, $capability, 'nopermissions', '');
239         }
241         $params = array('userids' => $userids, 'userid' => $userid);
242         $params = self::validate_parameters(self::create_contacts_parameters(), $params);
244         $warnings = array();
245         foreach ($params['userids'] as $id) {
246             if (!message_add_contact($id, 0, $userid)) {
247                 $warnings[] = array(
248                     'item' => 'user',
249                     'itemid' => $id,
250                     'warningcode' => 'contactnotcreated',
251                     'message' => 'The contact could not be created'
252                 );
253             }
254         }
255         return $warnings;
256     }
258     /**
259      * Create contacts return description.
260      *
261      * @deprecated since Moodle 3.6
262      * @return external_description
263      * @since Moodle 2.5
264      */
265     public static function create_contacts_returns() {
266         return new external_warnings();
267     }
269     /**
270      * Marking the method as deprecated.
271      *
272      * @return bool
273      */
274     public static function create_contacts_is_deprecated() {
275         return true;
276     }
278     /**
279      * Delete contacts parameters description.
280      *
281      * @return external_function_parameters
282      * @since Moodle 2.5
283      */
284     public static function delete_contacts_parameters() {
285         return new external_function_parameters(
286             array(
287                 'userids' => new external_multiple_structure(
288                     new external_value(PARAM_INT, 'User ID'),
289                     'List of user IDs'
290                 ),
291                 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
292                     current user', VALUE_DEFAULT, 0)
293             )
294         );
295     }
297     /**
298      * Delete contacts.
299      *
300      * @param array $userids array of user IDs.
301      * @param int $userid The id of the user we are deleting the contacts for
302      * @return null
303      * @since Moodle 2.5
304      */
305     public static function delete_contacts($userids, $userid = 0) {
306         global $CFG, $USER;
308         // Check if messaging is enabled.
309         if (empty($CFG->messaging)) {
310             throw new moodle_exception('disabled', 'message');
311         }
313         if (empty($userid)) {
314             $userid = $USER->id;
315         }
317         // Validate context.
318         $context = context_system::instance();
319         self::validate_context($context);
321         $capability = 'moodle/site:manageallmessaging';
322         if (($USER->id != $userid) && !has_capability($capability, $context)) {
323             throw new required_capability_exception($context, $capability, 'nopermissions', '');
324         }
326         $params = array('userids' => $userids, 'userid' => $userid);
327         $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
329         foreach ($params['userids'] as $id) {
330             message_remove_contact($id, $userid);
331         }
333         return null;
334     }
336     /**
337      * Delete contacts return description.
338      *
339      * @return external_description
340      * @since Moodle 2.5
341      */
342     public static function delete_contacts_returns() {
343         return null;
344     }
346     /**
347      * Block user parameters description.
348      *
349      * @return external_function_parameters
350      */
351     public static function block_user_parameters() {
352         return new external_function_parameters(
353             [
354                 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
355                 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
356             ]
357         );
358     }
360     /**
361      * Blocks a user.
362      *
363      * @param int $userid The id of the user who is blocking
364      * @param int $blockeduserid The id of the user being blocked
365      * @return external_description
366      */
367     public static function block_user(int $userid, int $blockeduserid) {
368         global $CFG, $USER;
370         // Check if messaging is enabled.
371         if (empty($CFG->messaging)) {
372             throw new moodle_exception('disabled', 'message');
373         }
375         // Validate context.
376         $context = context_system::instance();
377         self::validate_context($context);
379         $capability = 'moodle/site:manageallmessaging';
380         if (($USER->id != $userid) && !has_capability($capability, $context)) {
381             throw new required_capability_exception($context, $capability, 'nopermissions', '');
382         }
384         $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
385         $params = self::validate_parameters(self::block_user_parameters(), $params);
387         if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
388             \core_message\api::block_user($params['userid'], $params['blockeduserid']);
389         }
391         return [];
392     }
394     /**
395      * Block user return description.
396      *
397      * @return external_description
398      */
399     public static function block_user_returns() {
400         return new external_warnings();
401     }
403     /**
404      * Unblock user parameters description.
405      *
406      * @return external_function_parameters
407      */
408     public static function unblock_user_parameters() {
409         return new external_function_parameters(
410             [
411                 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
412                 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
413             ]
414         );
415     }
417     /**
418      * Unblock user.
419      *
420      * @param int $userid The id of the user who is unblocking
421      * @param int $unblockeduserid The id of the user being unblocked
422      */
423     public static function unblock_user(int $userid, int $unblockeduserid) {
424         global $CFG, $USER;
426         // Check if messaging is enabled.
427         if (empty($CFG->messaging)) {
428             throw new moodle_exception('disabled', 'message');
429         }
431         // Validate context.
432         $context = context_system::instance();
433         self::validate_context($context);
435         $capability = 'moodle/site:manageallmessaging';
436         if (($USER->id != $userid) && !has_capability($capability, $context)) {
437             throw new required_capability_exception($context, $capability, 'nopermissions', '');
438         }
440         $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
441         $params = self::validate_parameters(self::unblock_user_parameters(), $params);
443         \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
445         return [];
446     }
448     /**
449      * Unblock user return description.
450      *
451      * @return external_description
452      */
453     public static function unblock_user_returns() {
454         return new external_warnings();
455     }
457     /**
458      * Block contacts parameters description.
459      *
460      * @deprecated since Moodle 3.6
461      * @return external_function_parameters
462      * @since Moodle 2.5
463      */
464     public static function block_contacts_parameters() {
465         return new external_function_parameters(
466             array(
467                 'userids' => new external_multiple_structure(
468                     new external_value(PARAM_INT, 'User ID'),
469                     'List of user IDs'
470                 ),
471                 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
472                     current user', VALUE_DEFAULT, 0)
473             )
474         );
475     }
477     /**
478      * Block contacts.
479      *
480      * @deprecated since Moodle 3.6
481      * @param array $userids array of user IDs.
482      * @param int $userid The id of the user we are blocking the contacts for
483      * @return external_description
484      * @since Moodle 2.5
485      */
486     public static function block_contacts($userids, $userid = 0) {
487         global $CFG, $USER;
489         // Check if messaging is enabled.
490         if (empty($CFG->messaging)) {
491             throw new moodle_exception('disabled', 'message');
492         }
494         if (empty($userid)) {
495             $userid = $USER->id;
496         }
498         // Validate context.
499         $context = context_system::instance();
500         self::validate_context($context);
502         $capability = 'moodle/site:manageallmessaging';
503         if (($USER->id != $userid) && !has_capability($capability, $context)) {
504             throw new required_capability_exception($context, $capability, 'nopermissions', '');
505         }
507         $params = array('userids' => $userids, 'userid' => $userid);
508         $params = self::validate_parameters(self::block_contacts_parameters(), $params);
510         $warnings = array();
511         foreach ($params['userids'] as $id) {
512             if (!message_block_contact($id, $userid)) {
513                 $warnings[] = array(
514                     'item' => 'user',
515                     'itemid' => $id,
516                     'warningcode' => 'contactnotblocked',
517                     'message' => 'The contact could not be blocked'
518                 );
519             }
520         }
521         return $warnings;
522     }
524     /**
525      * Block contacts return description.
526      *
527      * @deprecated since Moodle 3.6
528      * @return external_description
529      * @since Moodle 2.5
530      */
531     public static function block_contacts_returns() {
532         return new external_warnings();
533     }
535     /**
536      * Marking the method as deprecated.
537      *
538      * @return bool
539      */
540     public static function block_contacts_is_deprecated() {
541         return true;
542     }
544     /**
545      * Unblock contacts parameters description.
546      *
547      * @deprecated since Moodle 3.6
548      * @return external_function_parameters
549      * @since Moodle 2.5
550      */
551     public static function unblock_contacts_parameters() {
552         return new external_function_parameters(
553             array(
554                 'userids' => new external_multiple_structure(
555                     new external_value(PARAM_INT, 'User ID'),
556                     'List of user IDs'
557                 ),
558                 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
559                     current user', VALUE_DEFAULT, 0)
560             )
561         );
562     }
564     /**
565      * Unblock contacts.
566      *
567      * @deprecated since Moodle 3.6
568      * @param array $userids array of user IDs.
569      * @param int $userid The id of the user we are unblocking the contacts for
570      * @return null
571      * @since Moodle 2.5
572      */
573     public static function unblock_contacts($userids, $userid = 0) {
574         global $CFG, $USER;
576         // Check if messaging is enabled.
577         if (empty($CFG->messaging)) {
578             throw new moodle_exception('disabled', 'message');
579         }
581         if (empty($userid)) {
582             $userid = $USER->id;
583         }
585         // Validate context.
586         $context = context_system::instance();
587         self::validate_context($context);
589         $capability = 'moodle/site:manageallmessaging';
590         if (($USER->id != $userid) && !has_capability($capability, $context)) {
591             throw new required_capability_exception($context, $capability, 'nopermissions', '');
592         }
594         $params = array('userids' => $userids, 'userid' => $userid);
595         $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
597         foreach ($params['userids'] as $id) {
598             message_unblock_contact($id, $userid);
599         }
601         return null;
602     }
604     /**
605      * Unblock contacts return description.
606      *
607      * @deprecated since Moodle 3.6
608      * @return external_description
609      * @since Moodle 2.5
610      */
611     public static function unblock_contacts_returns() {
612         return null;
613     }
615     /**
616      * Marking the method as deprecated.
617      *
618      * @return bool
619      */
620     public static function unblock_contacts_is_deprecated() {
621         return true;
622     }
624     /**
625      * Returns contact requests parameters description.
626      *
627      * @return external_function_parameters
628      */
629     public static function get_contact_requests_parameters() {
630         return new external_function_parameters(
631             [
632                 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for')
633             ]
634         );
635     }
637     /**
638      * Handles returning the contact requests for a user.
639      *
640      * This also includes the user data necessary to display information
641      * about the user.
642      *
643      * It will not include blocked users.
644      *
645      * @param int $userid The id of the user we want to get the contact requests for
646      */
647     public static function get_contact_requests(int $userid) {
648         global $CFG, $USER;
650         // Check if messaging is enabled.
651         if (empty($CFG->messaging)) {
652             throw new moodle_exception('disabled', 'message');
653         }
655         // Validate context.
656         $context = context_system::instance();
657         self::validate_context($context);
659         $capability = 'moodle/site:manageallmessaging';
660         if (($USER->id != $userid) && !has_capability($capability, $context)) {
661             throw new required_capability_exception($context, $capability, 'nopermissions', '');
662         }
664         $params = ['userid' => $userid];
665         $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
667         return \core_message\api::get_contact_requests($params['userid']);
668     }
670     /**
671      * Returns the contact requests return description.
672      *
673      * @return external_description
674      */
675     public static function get_contact_requests_returns() {
676         return new external_multiple_structure(
677             new external_single_structure(
678                 [
679                     'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'),
680                     'contactrequestid' => new external_value(PARAM_INT, 'The ID of the contact request'),
681                     'picture' => new external_value(core_user::get_property_type('picture'), 'The picture'),
682                     'firstname' => new external_value(core_user::get_property_type('firstname'),
683                         'The first name(s) of the user'),
684                     'lastname' => new external_value(core_user::get_property_type('lastname'),
685                         'The family name of the user'),
686                     'firstnamephonetic' => new external_value(core_user::get_property_type('firstnamephonetic'),
687                         'The phonetic first name of the user'),
688                     'lastnamephonetic' => new external_value(core_user::get_property_type('lastnamephonetic'),
689                         'The phonetic last name of the user'),
690                     'middlename' => new external_value(core_user::get_property_type('middlename'),
691                         'The middle name of the user'),
692                     'alternatename' => new external_value(core_user::get_property_type('alternatename'),
693                         'The alternate name of the user'),
694                     'email' => new external_value(core_user::get_property_type('email'), 'An email address')
695                 ]
696             )
697         );
698     }
700     /**
701      * Creates a contact request parameters description.
702      *
703      * @return external_function_parameters
704      */
705     public static function create_contact_request_parameters() {
706         return new external_function_parameters(
707             [
708                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
709                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
710             ]
711         );
712     }
714     /**
715      * Creates a contact request.
716      *
717      * @param int $userid The id of the user who is creating the contact request
718      * @param int $requesteduserid The id of the user being requested
719      */
720     public static function create_contact_request(int $userid, int $requesteduserid) {
721         global $CFG, $USER;
723         // Check if messaging is enabled.
724         if (empty($CFG->messaging)) {
725             throw new moodle_exception('disabled', 'message');
726         }
728         // Validate context.
729         $context = context_system::instance();
730         self::validate_context($context);
732         $capability = 'moodle/site:manageallmessaging';
733         if (($USER->id != $userid) && !has_capability($capability, $context)) {
734             throw new required_capability_exception($context, $capability, 'nopermissions', '');
735         }
737         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
738         $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
740         if (!\core_message\api::does_contact_request_exist($params['userid'], $params['requesteduserid'])) {
741             \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
742         }
744         return [];
745     }
747     /**
748      * Creates a contact request return description.
749      *
750      * @return external_description
751      */
752     public static function create_contact_request_returns() {
753         return new external_warnings();
754     }
756     /**
757      * Confirm a contact request parameters description.
758      *
759      * @return external_function_parameters
760      */
761     public static function confirm_contact_request_parameters() {
762         return new external_function_parameters(
763             [
764                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
765                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
766             ]
767         );
768     }
770     /**
771      * Confirm a contact request.
772      *
773      * @param int $userid The id of the user who is creating the contact request
774      * @param int $requesteduserid The id of the user being requested
775      */
776     public static function confirm_contact_request(int $userid, int $requesteduserid) {
777         global $CFG, $USER;
779         // Check if messaging is enabled.
780         if (empty($CFG->messaging)) {
781             throw new moodle_exception('disabled', 'message');
782         }
784         // Validate context.
785         $context = context_system::instance();
786         self::validate_context($context);
788         $capability = 'moodle/site:manageallmessaging';
789         if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
790             throw new required_capability_exception($context, $capability, 'nopermissions', '');
791         }
793         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
794         $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
796         \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
798         return [];
799     }
801     /**
802      * Confirm a contact request return description.
803      *
804      * @return external_description
805      */
806     public static function confirm_contact_request_returns() {
807         return new external_warnings();
808     }
810     /**
811      * Declines a contact request parameters description.
812      *
813      * @return external_function_parameters
814      */
815     public static function decline_contact_request_parameters() {
816         return new external_function_parameters(
817             [
818                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
819                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
820             ]
821         );
822     }
824     /**
825      * Declines a contact request.
826      *
827      * @param int $userid The id of the user who is creating the contact request
828      * @param int $requesteduserid The id of the user being requested
829      */
830     public static function decline_contact_request(int $userid, int $requesteduserid) {
831         global $CFG, $USER;
833         // Check if messaging is enabled.
834         if (empty($CFG->messaging)) {
835             throw new moodle_exception('disabled', 'message');
836         }
838         // Validate context.
839         $context = context_system::instance();
840         self::validate_context($context);
842         $capability = 'moodle/site:manageallmessaging';
843         if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
844             throw new required_capability_exception($context, $capability, 'nopermissions', '');
845         }
847         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
848         $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
850         \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
852         return [];
853     }
855     /**
856      * Declines a contact request return description.
857      *
858      * @return external_description
859      */
860     public static function decline_contact_request_returns() {
861         return new external_warnings();
862     }
864     /**
865      * Return the structure of a message area contact.
866      *
867      * @return external_single_structure
868      * @since Moodle 3.2
869      */
870     private static function get_messagearea_contact_structure() {
871         return new external_single_structure(
872             array(
873                 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
874                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
875                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
876                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
877                 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
878                 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
879                 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
880                 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
881                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
882                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
883                 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
884                 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
885                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
886                     VALUE_DEFAULT, null),
887             )
888         );
889     }
891     /**
892      * Return the structure of a message area message.
893      *
894      * @return external_single_structure
895      * @since Moodle 3.2
896      */
897     private static function get_messagearea_message_structure() {
898         return new external_single_structure(
899             array(
900                 'id' => new external_value(PARAM_INT, 'The id of the message'),
901                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
902                 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
903                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
904                 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
905                 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
906                 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
907                 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
908                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
909                 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
910             )
911         );
912     }
914     /**
915      * Get messagearea search users in course parameters.
916      *
917      * @return external_function_parameters
918      * @since 3.2
919      */
920     public static function data_for_messagearea_search_users_in_course_parameters() {
921         return new external_function_parameters(
922             array(
923                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
924                 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
925                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
926                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
927                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
928             )
929         );
930     }
932     /**
933      * Get messagearea search users in course results.
934      *
935      * @param int $userid The id of the user who is performing the search
936      * @param int $courseid The id of the course
937      * @param string $search The string being searched
938      * @param int $limitfrom
939      * @param int $limitnum
940      * @return stdClass
941      * @throws moodle_exception
942      * @since 3.2
943      */
944     public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
945                                                                        $limitnum = 0) {
946         global $CFG, $PAGE, $USER;
948         // Check if messaging is enabled.
949         if (empty($CFG->messaging)) {
950             throw new moodle_exception('disabled', 'message');
951         }
953         $systemcontext = context_system::instance();
955         $params = array(
956             'userid' => $userid,
957             'courseid' => $courseid,
958             'search' => $search,
959             'limitfrom' => $limitfrom,
960             'limitnum' => $limitnum
961         );
962         self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
963         self::validate_context($systemcontext);
965         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
966             throw new moodle_exception('You do not have permission to perform this action.');
967         }
969         $users = \core_message\api::search_users_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
970         $results = new \core_message\output\messagearea\user_search_results($users);
972         $renderer = $PAGE->get_renderer('core_message');
973         return $results->export_for_template($renderer);
974     }
976     /**
977      * Get messagearea search users in course returns.
978      *
979      * @return external_single_structure
980      * @since 3.2
981      */
982     public static function data_for_messagearea_search_users_in_course_returns() {
983         return new external_single_structure(
984             array(
985                 'contacts' => new external_multiple_structure(
986                     self::get_messagearea_contact_structure()
987                 ),
988             )
989         );
990     }
992     /**
993      * Get messagearea search users parameters.
994      *
995      * @return external_function_parameters
996      * @since 3.2
997      */
998     public static function data_for_messagearea_search_users_parameters() {
999         return new external_function_parameters(
1000             array(
1001                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1002                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1003                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1004             )
1005         );
1006     }
1008     /**
1009      * Get messagearea search users results.
1010      *
1011      * @param int $userid The id of the user who is performing the search
1012      * @param string $search The string being searched
1013      * @param int $limitnum
1014      * @return stdClass
1015      * @throws moodle_exception
1016      * @since 3.2
1017      */
1018     public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
1019         global $CFG, $PAGE, $USER;
1021         // Check if messaging is enabled.
1022         if (empty($CFG->messaging)) {
1023             throw new moodle_exception('disabled', 'message');
1024         }
1026         $systemcontext = context_system::instance();
1028         $params = array(
1029             'userid' => $userid,
1030             'search' => $search,
1031             'limitnum' => $limitnum
1032         );
1033         self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1034         self::validate_context($systemcontext);
1036         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1037             throw new moodle_exception('You do not have permission to perform this action.');
1038         }
1040         list($contacts, $courses, $noncontacts) = \core_message\api::search_users($userid, $search, $limitnum);
1041         $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1043         $renderer = $PAGE->get_renderer('core_message');
1044         return $search->export_for_template($renderer);
1045     }
1047     /**
1048      * Get messagearea search users returns.
1049      *
1050      * @return external_single_structure
1051      * @since 3.2
1052      */
1053     public static function data_for_messagearea_search_users_returns() {
1054         return new external_single_structure(
1055             array(
1056                 'contacts' => new external_multiple_structure(
1057                     self::get_messagearea_contact_structure()
1058                 ),
1059                 'courses' => new external_multiple_structure(
1060                     new external_single_structure(
1061                         array(
1062                             'id' => new external_value(PARAM_INT, 'The course id'),
1063                             'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1064                             'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1065                         )
1066                     )
1067                 ),
1068                 'noncontacts' => new external_multiple_structure(
1069                     self::get_messagearea_contact_structure()
1070                 )
1071             )
1072         );
1073     }
1075     /**
1076      * Get messagearea search messages parameters.
1077      *
1078      * @return external_function_parameters
1079      * @since 3.2
1080      */
1081     public static function data_for_messagearea_search_messages_parameters() {
1082         return new external_function_parameters(
1083             array(
1084                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1085                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1086                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1087                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1088             )
1089         );
1090     }
1092     /**
1093      * Get messagearea search messages results.
1094      *
1095      * @param int $userid The id of the user who is performing the search
1096      * @param string $search The string being searched
1097      * @param int $limitfrom
1098      * @param int $limitnum
1099      * @return stdClass
1100      * @throws moodle_exception
1101      * @since 3.2
1102      */
1103     public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1104         global $CFG, $PAGE, $USER;
1106         // Check if messaging is enabled.
1107         if (empty($CFG->messaging)) {
1108             throw new moodle_exception('disabled', 'message');
1109         }
1111         $systemcontext = context_system::instance();
1113         $params = array(
1114             'userid' => $userid,
1115             'search' => $search,
1116             'limitfrom' => $limitfrom,
1117             'limitnum' => $limitnum
1119         );
1120         self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1121         self::validate_context($systemcontext);
1123         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1124             throw new moodle_exception('You do not have permission to perform this action.');
1125         }
1127         $messages = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
1128         $results = new \core_message\output\messagearea\message_search_results($messages);
1130         $renderer = $PAGE->get_renderer('core_message');
1131         return $results->export_for_template($renderer);
1132     }
1134     /**
1135      * Get messagearea search messages returns.
1136      *
1137      * @return external_single_structure
1138      * @since 3.2
1139      */
1140     public static function data_for_messagearea_search_messages_returns() {
1141         return new external_single_structure(
1142             array(
1143                 'contacts' => new external_multiple_structure(
1144                     self::get_messagearea_contact_structure()
1145                 )
1146             )
1147         );
1148     }
1150     /**
1151      * The messagearea conversations parameters.
1152      *
1153      * @return external_function_parameters
1154      * @since 3.2
1155      */
1156     public static function data_for_messagearea_conversations_parameters() {
1157         return new external_function_parameters(
1158             array(
1159                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1160                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1161                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1162             )
1163         );
1164     }
1166     /**
1167      * Get messagearea conversations.
1168      *
1169      * @param int $userid The id of the user who we are viewing conversations for
1170      * @param int $limitfrom
1171      * @param int $limitnum
1172      * @return stdClass
1173      * @throws moodle_exception
1174      * @since 3.2
1175      */
1176     public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1177         global $CFG, $PAGE, $USER;
1179         // Check if messaging is enabled.
1180         if (empty($CFG->messaging)) {
1181             throw new moodle_exception('disabled', 'message');
1182         }
1184         $systemcontext = context_system::instance();
1186         $params = array(
1187             'userid' => $userid,
1188             'limitfrom' => $limitfrom,
1189             'limitnum' => $limitnum
1190         );
1191         self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1192         self::validate_context($systemcontext);
1194         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1195             throw new moodle_exception('You do not have permission to perform this action.');
1196         }
1198         $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum);
1199         $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1201         $renderer = $PAGE->get_renderer('core_message');
1202         return $conversations->export_for_template($renderer);
1203     }
1205     /**
1206      * The messagearea conversations return structure.
1207      *
1208      * @return external_single_structure
1209      * @since 3.2
1210      */
1211     public static function data_for_messagearea_conversations_returns() {
1212         return new external_single_structure(
1213             array(
1214                 'contacts' => new external_multiple_structure(
1215                     self::get_messagearea_contact_structure()
1216                 )
1217             )
1218         );
1219     }
1221     /**
1222      * The messagearea contacts return parameters.
1223      *
1224      * @return external_function_parameters
1225      * @since 3.2
1226      */
1227     public static function data_for_messagearea_contacts_parameters() {
1228         return self::data_for_messagearea_conversations_parameters();
1229     }
1231     /**
1232      * Get messagearea contacts parameters.
1233      *
1234      * @param int $userid The id of the user who we are viewing conversations for
1235      * @param int $limitfrom
1236      * @param int $limitnum
1237      * @return stdClass
1238      * @throws moodle_exception
1239      * @since 3.2
1240      */
1241     public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1242         global $CFG, $PAGE, $USER;
1244         // Check if messaging is enabled.
1245         if (empty($CFG->messaging)) {
1246             throw new moodle_exception('disabled', 'message');
1247         }
1249         $systemcontext = context_system::instance();
1251         $params = array(
1252             'userid' => $userid,
1253             'limitfrom' => $limitfrom,
1254             'limitnum' => $limitnum
1255         );
1256         self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1257         self::validate_context($systemcontext);
1259         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1260             throw new moodle_exception('You do not have permission to perform this action.');
1261         }
1263         $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
1264         $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1266         $renderer = $PAGE->get_renderer('core_message');
1267         return $contacts->export_for_template($renderer);
1268     }
1270     /**
1271      * The messagearea contacts return structure.
1272      *
1273      * @return external_single_structure
1274      * @since 3.2
1275      */
1276     public static function data_for_messagearea_contacts_returns() {
1277         return self::data_for_messagearea_conversations_returns();
1278     }
1280     /**
1281      * The messagearea messages parameters.
1282      *
1283      * @return external_function_parameters
1284      * @since 3.2
1285      */
1286     public static function data_for_messagearea_messages_parameters() {
1287         return new external_function_parameters(
1288             array(
1289                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1290                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1291                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1292                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1293                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1294                 'timefrom' => new external_value(PARAM_INT,
1295                     'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1296             )
1297         );
1298     }
1300     /**
1301      * Get messagearea messages.
1302      *
1303      * @param int $currentuserid The current user's id
1304      * @param int $otheruserid The other user's id
1305      * @param int $limitfrom
1306      * @param int $limitnum
1307      * @param boolean $newest
1308      * @return stdClass
1309      * @throws moodle_exception
1310      * @since 3.2
1311      */
1312     public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
1313                                                          $newest = false, $timefrom = 0) {
1314         global $CFG, $PAGE, $USER;
1316         // Check if messaging is enabled.
1317         if (empty($CFG->messaging)) {
1318             throw new moodle_exception('disabled', 'message');
1319         }
1321         $systemcontext = context_system::instance();
1323         $params = array(
1324             'currentuserid' => $currentuserid,
1325             'otheruserid' => $otheruserid,
1326             'limitfrom' => $limitfrom,
1327             'limitnum' => $limitnum,
1328             'newest' => $newest,
1329             'timefrom' => $timefrom,
1330         );
1331         self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
1332         self::validate_context($systemcontext);
1334         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1335             throw new moodle_exception('You do not have permission to perform this action.');
1336         }
1338         if ($newest) {
1339             $sort = 'timecreated DESC';
1340         } else {
1341             $sort = 'timecreated ASC';
1342         }
1344         // We need to enforce a one second delay on messages to avoid race conditions of current
1345         // messages still being sent.
1346         //
1347         // There is a chance that we could request messages before the current time's
1348         // second has elapsed and while other messages are being sent in that same second. In which
1349         // case those messages will be lost.
1350         //
1351         // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1352         if (!empty($timefrom)) {
1353             $timeto = time() - 1;
1354         } else {
1355             $timeto = 0;
1356         }
1358         // No requesting messages from the current time, as stated above.
1359         if ($timefrom == time()) {
1360             $messages = [];
1361         } else {
1362             $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
1363                                                         $limitnum, $sort, $timefrom, $timeto);
1364         }
1366         $messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
1368         $renderer = $PAGE->get_renderer('core_message');
1369         return $messages->export_for_template($renderer);
1370     }
1372     /**
1373      * The messagearea messages return structure.
1374      *
1375      * @return external_single_structure
1376      * @since 3.2
1377      */
1378     public static function data_for_messagearea_messages_returns() {
1379         return new external_single_structure(
1380             array(
1381                 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
1382                     the messages on behalf of?'),
1383                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1384                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1385                 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
1386                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1387                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1388                 'messages' => new external_multiple_structure(
1389                     self::get_messagearea_message_structure()
1390                 ),
1391                 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
1392             )
1393         );
1394     }
1396     /**
1397      * The get most recent message return parameters.
1398      *
1399      * @return external_function_parameters
1400      * @since 3.2
1401      */
1402     public static function data_for_messagearea_get_most_recent_message_parameters() {
1403         return new external_function_parameters(
1404             array(
1405                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1406                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1407             )
1408         );
1409     }
1411     /**
1412      * Get the most recent message in a conversation.
1413      *
1414      * @param int $currentuserid The current user's id
1415      * @param int $otheruserid The other user's id
1416      * @return stdClass
1417      * @throws moodle_exception
1418      * @since 3.2
1419      */
1420     public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
1421         global $CFG, $PAGE, $USER;
1423         // Check if messaging is enabled.
1424         if (empty($CFG->messaging)) {
1425             throw new moodle_exception('disabled', 'message');
1426         }
1428         $systemcontext = context_system::instance();
1430         $params = array(
1431             'currentuserid' => $currentuserid,
1432             'otheruserid' => $otheruserid
1433         );
1434         self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
1435         self::validate_context($systemcontext);
1437         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1438             throw new moodle_exception('You do not have permission to perform this action.');
1439         }
1441         $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
1442         $message = new \core_message\output\messagearea\message($message);
1444         $renderer = $PAGE->get_renderer('core_message');
1445         return $message->export_for_template($renderer);
1446     }
1448     /**
1449      * The get most recent message return structure.
1450      *
1451      * @return external_single_structure
1452      * @since 3.2
1453      */
1454     public static function data_for_messagearea_get_most_recent_message_returns() {
1455         return self::get_messagearea_message_structure();
1456     }
1458     /**
1459      * The get profile parameters.
1460      *
1461      * @return external_function_parameters
1462      * @since 3.2
1463      */
1464     public static function data_for_messagearea_get_profile_parameters() {
1465         return new external_function_parameters(
1466             array(
1467                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1468                 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
1469             )
1470         );
1471     }
1473     /**
1474      * Get the profile information for a contact.
1475      *
1476      * @param int $currentuserid The current user's id
1477      * @param int $otheruserid The id of the user whose profile we are viewing
1478      * @return stdClass
1479      * @throws moodle_exception
1480      * @since 3.2
1481      */
1482     public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
1483         global $CFG, $PAGE, $USER;
1485         // Check if messaging is enabled.
1486         if (empty($CFG->messaging)) {
1487             throw new moodle_exception('disabled', 'message');
1488         }
1490         $systemcontext = context_system::instance();
1492         $params = array(
1493             'currentuserid' => $currentuserid,
1494             'otheruserid' => $otheruserid
1495         );
1496         self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
1497         self::validate_context($systemcontext);
1499         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1500             throw new moodle_exception('You do not have permission to perform this action.');
1501         }
1503         $profile = \core_message\api::get_profile($currentuserid, $otheruserid);
1504         $profile = new \core_message\output\messagearea\profile($profile);
1506         $renderer = $PAGE->get_renderer('core_message');
1507         return $profile->export_for_template($renderer);
1508     }
1510     /**
1511      * The get profile return structure.
1512      *
1513      * @return external_single_structure
1514      * @since 3.2
1515      */
1516     public static function data_for_messagearea_get_profile_returns() {
1517         return new external_single_structure(
1518             array(
1519                 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
1520                 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
1521                 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
1522                 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
1523                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1524                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1525                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1526                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1527                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1528                 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
1529                 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
1530             )
1531         );
1532     }
1534     /**
1535      * Get contacts parameters description.
1536      *
1537      * @return external_function_parameters
1538      * @since Moodle 2.5
1539      */
1540     public static function get_contacts_parameters() {
1541         return new external_function_parameters(array());
1542     }
1544     /**
1545      * Get contacts.
1546      *
1547      * @return external_description
1548      * @since Moodle 2.5
1549      */
1550     public static function get_contacts() {
1551         global $CFG, $PAGE, $USER;
1553         // Check if messaging is enabled.
1554         if (empty($CFG->messaging)) {
1555             throw new moodle_exception('disabled', 'message');
1556         }
1558         require_once($CFG->dirroot . '/user/lib.php');
1560         $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
1561         $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
1562         foreach ($contacts as $contact) {
1563             // Set the mode.
1564             $mode = 'offline';
1565             if (\core_message\helper::is_online($contact->lastaccess)) {
1566                 $mode = 'online';
1567             }
1569             $newcontact = array(
1570                 'id' => $contact->id,
1571                 'fullname' => fullname($contact),
1572                 'unread' => $contact->messagecount
1573             );
1575             $userpicture = new user_picture($contact);
1576             $userpicture->size = 1; // Size f1.
1577             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1578             $userpicture->size = 0; // Size f2.
1579             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1581             $allcontacts[$mode][$contact->id] = $newcontact;
1582         }
1584         $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
1585         foreach ($strangers as $contact) {
1586             $newcontact = array(
1587                 'id' => $contact->id,
1588                 'fullname' => fullname($contact),
1589                 'unread' => $contact->messagecount
1590             );
1592             $userpicture = new user_picture($contact);
1593             $userpicture->size = 1; // Size f1.
1594             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1595             $userpicture->size = 0; // Size f2.
1596             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1598             $allcontacts['strangers'][$contact->id] = $newcontact;
1599         }
1601         // Add noreply user and support user to the list, if they don't exist.
1602         $supportuser = core_user::get_support_user();
1603         if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
1604             $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
1605             if ($supportuser->messagecount > 0) {
1606                 $supportuser->fullname = fullname($supportuser);
1607                 $supportuser->unread = $supportuser->messagecount;
1608                 $allcontacts['strangers'][$supportuser->id] = $supportuser;
1609             }
1610         }
1612         $noreplyuser = core_user::get_noreply_user();
1613         if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
1614             $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
1615             if ($noreplyuser->messagecount > 0) {
1616                 $noreplyuser->fullname = fullname($noreplyuser);
1617                 $noreplyuser->unread = $noreplyuser->messagecount;
1618                 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
1619             }
1620         }
1622         return $allcontacts;
1623     }
1625     /**
1626      * Get contacts return description.
1627      *
1628      * @return external_description
1629      * @since Moodle 2.5
1630      */
1631     public static function get_contacts_returns() {
1632         return new external_single_structure(
1633             array(
1634                 'online' => new external_multiple_structure(
1635                     new external_single_structure(
1636                         array(
1637                             'id' => new external_value(PARAM_INT, 'User ID'),
1638                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1639                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1640                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1641                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1642                         )
1643                     ),
1644                     'List of online contacts'
1645                 ),
1646                 'offline' => new external_multiple_structure(
1647                     new external_single_structure(
1648                         array(
1649                             'id' => new external_value(PARAM_INT, 'User ID'),
1650                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1651                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1652                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1653                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1654                         )
1655                     ),
1656                     'List of offline contacts'
1657                 ),
1658                 'strangers' => new external_multiple_structure(
1659                     new external_single_structure(
1660                         array(
1661                             'id' => new external_value(PARAM_INT, 'User ID'),
1662                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1663                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1664                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1665                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1666                         )
1667                     ),
1668                     'List of users that are not in the user\'s contact list but have sent a message'
1669                 )
1670             )
1671         );
1672     }
1674     /**
1675      * Search contacts parameters description.
1676      *
1677      * @return external_function_parameters
1678      * @since Moodle 2.5
1679      */
1680     public static function search_contacts_parameters() {
1681         return new external_function_parameters(
1682             array(
1683                 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
1684                 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
1685                     VALUE_DEFAULT, false)
1686             )
1687         );
1688     }
1690     /**
1691      * Search contacts.
1692      *
1693      * @param string $searchtext query string.
1694      * @param bool $onlymycourses limit the search to the user's courses only.
1695      * @return external_description
1696      * @since Moodle 2.5
1697      */
1698     public static function search_contacts($searchtext, $onlymycourses = false) {
1699         global $CFG, $USER, $PAGE;
1700         require_once($CFG->dirroot . '/user/lib.php');
1702         // Check if messaging is enabled.
1703         if (empty($CFG->messaging)) {
1704             throw new moodle_exception('disabled', 'message');
1705         }
1707         require_once($CFG->libdir . '/enrollib.php');
1709         $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
1710         $params = self::validate_parameters(self::search_contacts_parameters(), $params);
1712         // Extra validation, we do not allow empty queries.
1713         if ($params['searchtext'] === '') {
1714             throw new moodle_exception('querystringcannotbeempty');
1715         }
1717         $courseids = array();
1718         if ($params['onlymycourses']) {
1719             $mycourses = enrol_get_my_courses(array('id'));
1720             foreach ($mycourses as $mycourse) {
1721                 $courseids[] = $mycourse->id;
1722             }
1723         } else {
1724             $courseids[] = SITEID;
1725         }
1727         // Retrieving the users matching the query.
1728         $users = message_search_users($courseids, $params['searchtext']);
1729         $results = array();
1730         foreach ($users as $user) {
1731             $results[$user->id] = $user;
1732         }
1734         // Reorganising information.
1735         foreach ($results as &$user) {
1736             $newuser = array(
1737                 'id' => $user->id,
1738                 'fullname' => fullname($user)
1739             );
1741             // Avoid undefined property notice as phone not specified.
1742             $user->phone1 = null;
1743             $user->phone2 = null;
1745             $userpicture = new user_picture($user);
1746             $userpicture->size = 1; // Size f1.
1747             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1748             $userpicture->size = 0; // Size f2.
1749             $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1751             $user = $newuser;
1752         }
1754         return $results;
1755     }
1757     /**
1758      * Search contacts return description.
1759      *
1760      * @return external_description
1761      * @since Moodle 2.5
1762      */
1763     public static function search_contacts_returns() {
1764         return new external_multiple_structure(
1765             new external_single_structure(
1766                 array(
1767                     'id' => new external_value(PARAM_INT, 'User ID'),
1768                     'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1769                     'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1770                     'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
1771                 )
1772             ),
1773             'List of contacts'
1774         );
1775     }
1777     /**
1778      * Get messages parameters description.
1779      *
1780      * @return external_function_parameters
1781      * @since 2.8
1782      */
1783     public static function get_messages_parameters() {
1784         return new external_function_parameters(
1785             array(
1786                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1787                 'useridfrom' => new external_value(
1788                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1789                     VALUE_DEFAULT, 0),
1790                 'type' => new external_value(
1791                     PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
1792                     VALUE_DEFAULT, 'both'),
1793                 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
1794                 'newestfirst' => new external_value(
1795                     PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
1796                     VALUE_DEFAULT, true),
1797                 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
1798                 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
1799             )
1800         );
1801     }
1803     /**
1804      * Get messages function implementation.
1805      *
1806      * @since  2.8
1807      * @throws invalid_parameter_exception
1808      * @throws moodle_exception
1809      * @param  int      $useridto       the user id who received the message
1810      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
1811      * @param  string   $type           type of message to return, expected values: notifications, conversations and both
1812      * @param  bool     $read           true for retreiving read messages, false for unread
1813      * @param  bool     $newestfirst    true for ordering by newest first, false for oldest first
1814      * @param  int      $limitfrom      limit from
1815      * @param  int      $limitnum       limit num
1816      * @return external_description
1817      */
1818     public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
1819                                         $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
1820         global $CFG, $USER;
1822         $warnings = array();
1824         $params = array(
1825             'useridto' => $useridto,
1826             'useridfrom' => $useridfrom,
1827             'type' => $type,
1828             'read' => $read,
1829             'newestfirst' => $newestfirst,
1830             'limitfrom' => $limitfrom,
1831             'limitnum' => $limitnum
1832         );
1834         $params = self::validate_parameters(self::get_messages_parameters(), $params);
1836         $context = context_system::instance();
1837         self::validate_context($context);
1839         $useridto = $params['useridto'];
1840         $useridfrom = $params['useridfrom'];
1841         $type = $params['type'];
1842         $read = $params['read'];
1843         $newestfirst = $params['newestfirst'];
1844         $limitfrom = $params['limitfrom'];
1845         $limitnum = $params['limitnum'];
1847         $allowedvalues = array('notifications', 'conversations', 'both');
1848         if (!in_array($type, $allowedvalues)) {
1849             throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
1850                 'allowed values are: ' . implode(',', $allowedvalues));
1851         }
1853         // Check if private messaging between users is allowed.
1854         if (empty($CFG->messaging)) {
1855             // If we are retreiving only conversations, and messaging is disabled, throw an exception.
1856             if ($type == "conversations") {
1857                 throw new moodle_exception('disabled', 'message');
1858             }
1859             if ($type == "both") {
1860                 $warning = array();
1861                 $warning['item'] = 'message';
1862                 $warning['itemid'] = $USER->id;
1863                 $warning['warningcode'] = '1';
1864                 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
1865                     Only notifications will be returned';
1866                 $warnings[] = $warning;
1867             }
1868         }
1870         if (!empty($useridto)) {
1871             if (core_user::is_real_user($useridto)) {
1872                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1873             } else {
1874                 throw new moodle_exception('invaliduser');
1875             }
1876         }
1878         if (!empty($useridfrom)) {
1879             // We use get_user here because the from user can be the noreply or support user.
1880             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1881         }
1883         // Check if the current user is the sender/receiver or just a privileged user.
1884         if ($useridto != $USER->id and $useridfrom != $USER->id and
1885              !has_capability('moodle/site:readallmessages', $context)) {
1886             throw new moodle_exception('accessdenied', 'admin');
1887         }
1889         // Which type of messages to retrieve.
1890         $notifications = -1;
1891         if ($type != 'both') {
1892             $notifications = ($type == 'notifications') ? 1 : 0;
1893         }
1895         $orderdirection = $newestfirst ? 'DESC' : 'ASC';
1896         $sort = "mr.timecreated $orderdirection";
1898         if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
1899             $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
1901             // In some cases, we don't need to get the to/from user objects from the sql query.
1902             $userfromfullname = '';
1903             $usertofullname = '';
1905             // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
1906             if (!empty($useridto)) {
1907                 $usertofullname = fullname($userto, $canviewfullname);
1908                 // The user from may or may not be filled.
1909                 if (!empty($useridfrom)) {
1910                     $userfromfullname = fullname($userfrom, $canviewfullname);
1911                 }
1912             } else {
1913                 // If the useridto field is empty, the useridfrom must be filled.
1914                 $userfromfullname = fullname($userfrom, $canviewfullname);
1915             }
1916             foreach ($messages as $mid => $message) {
1918                 // Do not return deleted messages.
1919                 if (!$message->notification) {
1920                     if (($useridto == $USER->id and $message->timeusertodeleted) or
1921                         ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
1922                         unset($messages[$mid]);
1923                         continue;
1924                     }
1925                 }
1927                 // We need to get the user from the query.
1928                 if (empty($userfromfullname)) {
1929                     // Check for non-reply and support users.
1930                     if (core_user::is_real_user($message->useridfrom)) {
1931                         $user = new stdClass();
1932                         $user = username_load_fields_from_object($user, $message, 'userfrom');
1933                         $message->userfromfullname = fullname($user, $canviewfullname);
1934                     } else {
1935                         $user = core_user::get_user($message->useridfrom);
1936                         $message->userfromfullname = fullname($user, $canviewfullname);
1937                     }
1938                 } else {
1939                     $message->userfromfullname = $userfromfullname;
1940                 }
1942                 // We need to get the user from the query.
1943                 if (empty($usertofullname)) {
1944                     $user = new stdClass();
1945                     $user = username_load_fields_from_object($user, $message, 'userto');
1946                     $message->usertofullname = fullname($user, $canviewfullname);
1947                 } else {
1948                     $message->usertofullname = $usertofullname;
1949                 }
1951                 $message->text = message_format_message_text($message);
1952                 $messages[$mid] = (array) $message;
1953             }
1954         }
1956         $results = array(
1957             'messages' => $messages,
1958             'warnings' => $warnings
1959         );
1961         return $results;
1962     }
1964     /**
1965      * Get messages return description.
1966      *
1967      * @return external_single_structure
1968      * @since 2.8
1969      */
1970     public static function get_messages_returns() {
1971         return new external_single_structure(
1972             array(
1973                 'messages' => new external_multiple_structure(
1974                     new external_single_structure(
1975                         array(
1976                             'id' => new external_value(PARAM_INT, 'Message id'),
1977                             'useridfrom' => new external_value(PARAM_INT, 'User from id'),
1978                             'useridto' => new external_value(PARAM_INT, 'User to id'),
1979                             'subject' => new external_value(PARAM_TEXT, 'The message subject'),
1980                             'text' => new external_value(PARAM_RAW, 'The message text formated'),
1981                             'fullmessage' => new external_value(PARAM_RAW, 'The message'),
1982                             'fullmessageformat' => new external_format_value('fullmessage'),
1983                             'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
1984                             'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
1985                             'notification' => new external_value(PARAM_INT, 'Is a notification?'),
1986                             'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
1987                             'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
1988                             'timecreated' => new external_value(PARAM_INT, 'Time created'),
1989                             'timeread' => new external_value(PARAM_INT, 'Time read'),
1990                             'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
1991                             'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
1992                         ), 'message'
1993                     )
1994                 ),
1995                 'warnings' => new external_warnings()
1996             )
1997         );
1998     }
2000     /**
2001      * Mark all notifications as read parameters description.
2002      *
2003      * @return external_function_parameters
2004      * @since 3.2
2005      */
2006     public static function mark_all_notifications_as_read_parameters() {
2007         return new external_function_parameters(
2008             array(
2009                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2010                 'useridfrom' => new external_value(
2011                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2012                     VALUE_DEFAULT, 0),
2013             )
2014         );
2015     }
2017     /**
2018      * Mark all notifications as read function.
2019      *
2020      * @since  3.2
2021      * @throws invalid_parameter_exception
2022      * @throws moodle_exception
2023      * @param  int      $useridto       the user id who received the message
2024      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
2025      * @return external_description
2026      */
2027     public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2028         global $USER;
2030         $params = self::validate_parameters(
2031             self::mark_all_notifications_as_read_parameters(),
2032             array(
2033                 'useridto' => $useridto,
2034                 'useridfrom' => $useridfrom,
2035             )
2036         );
2038         $context = context_system::instance();
2039         self::validate_context($context);
2041         $useridto = $params['useridto'];
2042         $useridfrom = $params['useridfrom'];
2044         if (!empty($useridto)) {
2045             if (core_user::is_real_user($useridto)) {
2046                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2047             } else {
2048                 throw new moodle_exception('invaliduser');
2049             }
2050         }
2052         if (!empty($useridfrom)) {
2053             // We use get_user here because the from user can be the noreply or support user.
2054             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2055         }
2057         // Check if the current user is the sender/receiver or just a privileged user.
2058         if ($useridto != $USER->id and $useridfrom != $USER->id and
2059             // The deleteanymessage cap seems more reasonable here than readallmessages.
2060              !has_capability('moodle/site:deleteanymessage', $context)) {
2061             throw new moodle_exception('accessdenied', 'admin');
2062         }
2064         \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2066         return true;
2067     }
2069     /**
2070      * Mark all notifications as read return description.
2071      *
2072      * @return external_single_structure
2073      * @since 3.2
2074      */
2075     public static function mark_all_notifications_as_read_returns() {
2076         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2077     }
2079     /**
2080      * Get unread conversations count parameters description.
2081      *
2082      * @return external_function_parameters
2083      * @since 3.2
2084      */
2085     public static function get_unread_conversations_count_parameters() {
2086         return new external_function_parameters(
2087             array(
2088                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2089             )
2090         );
2091     }
2093     /**
2094      * Get unread messages count function.
2095      *
2096      * @since  3.2
2097      * @throws invalid_parameter_exception
2098      * @throws moodle_exception
2099      * @param  int      $useridto       the user id who received the message
2100      * @return external_description
2101      */
2102     public static function get_unread_conversations_count($useridto) {
2103         global $USER, $CFG;
2105         // Check if messaging is enabled.
2106         if (empty($CFG->messaging)) {
2107             throw new moodle_exception('disabled', 'message');
2108         }
2110         $params = self::validate_parameters(
2111             self::get_unread_conversations_count_parameters(),
2112             array('useridto' => $useridto)
2113         );
2115         $context = context_system::instance();
2116         self::validate_context($context);
2118         $useridto = $params['useridto'];
2120         if (!empty($useridto)) {
2121             if (core_user::is_real_user($useridto)) {
2122                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2123             } else {
2124                 throw new moodle_exception('invaliduser');
2125             }
2126         } else {
2127             $useridto = $USER->id;
2128         }
2130         // Check if the current user is the receiver or just a privileged user.
2131         if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2132             throw new moodle_exception('accessdenied', 'admin');
2133         }
2135         return \core_message\api::count_unread_conversations($userto);
2136     }
2138     /**
2139      * Get unread conversations count return description.
2140      *
2141      * @return external_single_structure
2142      * @since 3.2
2143      */
2144     public static function get_unread_conversations_count_returns() {
2145         return new external_value(PARAM_INT, 'The count of unread messages for the user');
2146     }
2148     /**
2149      * Get blocked users parameters description.
2150      *
2151      * @return external_function_parameters
2152      * @since 2.9
2153      */
2154     public static function get_blocked_users_parameters() {
2155         return new external_function_parameters(
2156             array(
2157                 'userid' => new external_value(PARAM_INT,
2158                                 'the user whose blocked users we want to retrieve',
2159                                 VALUE_REQUIRED),
2160             )
2161         );
2162     }
2164     /**
2165      * Retrieve a list of users blocked
2166      *
2167      * @param  int $userid the user whose blocked users we want to retrieve
2168      * @return external_description
2169      * @since 2.9
2170      */
2171     public static function get_blocked_users($userid) {
2172         global $CFG, $USER, $PAGE;
2174         // Warnings array, it can be empty at the end but is mandatory.
2175         $warnings = array();
2177         // Validate params.
2178         $params = array(
2179             'userid' => $userid
2180         );
2181         $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
2182         $userid = $params['userid'];
2184         // Validate context.
2185         $context = context_system::instance();
2186         self::validate_context($context);
2188         // Check if private messaging between users is allowed.
2189         if (empty($CFG->messaging)) {
2190             throw new moodle_exception('disabled', 'message');
2191         }
2193         $user = core_user::get_user($userid, '*', MUST_EXIST);
2194         core_user::require_active_user($user);
2196         // Check if we have permissions for retrieve the information.
2197         $capability = 'moodle/site:manageallmessaging';
2198         if (($USER->id != $userid) && !has_capability($capability, $context)) {
2199             throw new required_capability_exception($context, $capability, 'nopermissions', '');
2200         }
2202         // Now, we can get safely all the blocked users.
2203         $users = \core_message\api::get_blocked_users($user->id);
2205         $blockedusers = array();
2206         foreach ($users as $user) {
2207             $newuser = array(
2208                 'id' => $user->id,
2209                 'fullname' => fullname($user),
2210             );
2212             $userpicture = new user_picture($user);
2213             $userpicture->size = 1; // Size f1.
2214             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2216             $blockedusers[] = $newuser;
2217         }
2219         $results = array(
2220             'users' => $blockedusers,
2221             'warnings' => $warnings
2222         );
2223         return $results;
2224     }
2226     /**
2227      * Get blocked users return description.
2228      *
2229      * @return external_single_structure
2230      * @since 2.9
2231      */
2232     public static function get_blocked_users_returns() {
2233         return new external_single_structure(
2234             array(
2235                 'users' => new external_multiple_structure(
2236                     new external_single_structure(
2237                         array(
2238                             'id' => new external_value(PARAM_INT, 'User ID'),
2239                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2240                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
2241                         )
2242                     ),
2243                     'List of blocked users'
2244                 ),
2245                 'warnings' => new external_warnings()
2246             )
2247         );
2248     }
2250     /**
2251      * Returns description of method parameters
2252      *
2253      * @return external_function_parameters
2254      * @since 2.9
2255      */
2256     public static function mark_message_read_parameters() {
2257         return new external_function_parameters(
2258             array(
2259                 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
2260                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
2261                     VALUE_DEFAULT, 0)
2262             )
2263         );
2264     }
2266     /**
2267      * Mark a single message as read, trigger message_viewed event
2268      *
2269      * @param  int $messageid id of the message (in the message table)
2270      * @param  int $timeread timestamp for when the message should be marked read
2271      * @return external_description
2272      * @throws invalid_parameter_exception
2273      * @throws moodle_exception
2274      * @since 2.9
2275      */
2276     public static function mark_message_read($messageid, $timeread) {
2277         global $CFG, $DB, $USER;
2279         // Check if private messaging between users is allowed.
2280         if (empty($CFG->messaging)) {
2281             throw new moodle_exception('disabled', 'message');
2282         }
2284         // Warnings array, it can be empty at the end but is mandatory.
2285         $warnings = array();
2287         // Validate params.
2288         $params = array(
2289             'messageid' => $messageid,
2290             'timeread' => $timeread
2291         );
2292         $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
2294         if (empty($params['timeread'])) {
2295             $timeread = time();
2296         } else {
2297             $timeread = $params['timeread'];
2298         }
2300         // Validate context.
2301         $context = context_system::instance();
2302         self::validate_context($context);
2304         $sql = "SELECT m.*, mcm.userid as useridto
2305                   FROM {messages} m
2306             INNER JOIN {message_conversations} mc
2307                     ON m.conversationid = mc.id
2308             INNER JOIN {message_conversation_members} mcm
2309                     ON mcm.conversationid = mc.id
2310              LEFT JOIN {message_user_actions} mua
2311                     ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
2312                  WHERE mua.id is NULL
2313                    AND mcm.userid != m.useridfrom
2314                    AND m.id = ?";
2315         $messageparams = [];
2316         $messageparams[] = $USER->id;
2317         $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
2318         $messageparams[] = $params['messageid'];
2319         $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
2321         if ($message->useridto != $USER->id) {
2322             throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
2323         }
2325         \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
2327         $results = array(
2328             'messageid' => $message->id,
2329             'warnings' => $warnings
2330         );
2331         return $results;
2332     }
2334     /**
2335      * Returns description of method result value
2336      *
2337      * @return external_description
2338      * @since 2.9
2339      */
2340     public static function mark_message_read_returns() {
2341         return new external_single_structure(
2342             array(
2343                 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
2344                 'warnings' => new external_warnings()
2345             )
2346         );
2347     }
2349     /**
2350      * Returns description of method parameters
2351      *
2352      * @return external_function_parameters
2353      */
2354     public static function mark_notification_read_parameters() {
2355         return new external_function_parameters(
2356             array(
2357                 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2358                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
2359                     VALUE_DEFAULT, 0)
2360             )
2361         );
2362     }
2364     /**
2365      * Mark a single notification as read.
2366      *
2367      * This will trigger a 'notification_viewed' event.
2368      *
2369      * @param int $notificationid id of the notification
2370      * @param int $timeread timestamp for when the notification should be marked read
2371      * @return external_description
2372      * @throws invalid_parameter_exception
2373      * @throws moodle_exception
2374      */
2375     public static function mark_notification_read($notificationid, $timeread) {
2376         global $CFG, $DB, $USER;
2378         // Check if private messaging between users is allowed.
2379         if (empty($CFG->messaging)) {
2380             throw new moodle_exception('disabled', 'message');
2381         }
2383         // Warnings array, it can be empty at the end but is mandatory.
2384         $warnings = array();
2386         // Validate params.
2387         $params = array(
2388             'notificationid' => $notificationid,
2389             'timeread' => $timeread
2390         );
2391         $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
2393         if (empty($params['timeread'])) {
2394             $timeread = time();
2395         } else {
2396             $timeread = $params['timeread'];
2397         }
2399         // Validate context.
2400         $context = context_system::instance();
2401         self::validate_context($context);
2403         $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
2405         if ($notification->useridto != $USER->id) {
2406             throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
2407                 'notification as read');
2408         }
2410         \core_message\api::mark_notification_as_read($notification, $timeread);
2412         $results = array(
2413             'notificationid' => $notification->id,
2414             'warnings' => $warnings
2415         );
2417         return $results;
2418     }
2420     /**
2421      * Returns description of method result value
2422      *
2423      * @return external_description
2424      */
2425     public static function mark_notification_read_returns() {
2426         return new external_single_structure(
2427             array(
2428                 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2429                 'warnings' => new external_warnings()
2430             )
2431         );
2432     }
2434     /**
2435      * Mark all messages as read parameters description.
2436      *
2437      * @return external_function_parameters
2438      * @since 3.2
2439      */
2440     public static function mark_all_messages_as_read_parameters() {
2441         return new external_function_parameters(
2442             array(
2443                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2444                 'useridfrom' => new external_value(
2445                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2446                     VALUE_DEFAULT, 0),
2447             )
2448         );
2449     }
2451     /**
2452      * Mark all notifications as read function.
2453      *
2454      * @since  3.2
2455      * @throws invalid_parameter_exception
2456      * @throws moodle_exception
2457      * @param  int      $useridto       the user id who received the message
2458      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
2459      * @return external_description
2460      */
2461     public static function mark_all_messages_as_read($useridto, $useridfrom) {
2462         global $USER, $CFG;
2464         // Check if messaging is enabled.
2465         if (empty($CFG->messaging)) {
2466             throw new moodle_exception('disabled', 'message');
2467         }
2469         $params = self::validate_parameters(
2470             self::mark_all_messages_as_read_parameters(),
2471             array(
2472                 'useridto' => $useridto,
2473                 'useridfrom' => $useridfrom,
2474             )
2475         );
2477         $context = context_system::instance();
2478         self::validate_context($context);
2480         $useridto = $params['useridto'];
2481         $useridfrom = $params['useridfrom'];
2483         if (!empty($useridto)) {
2484             if (core_user::is_real_user($useridto)) {
2485                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2486             } else {
2487                 throw new moodle_exception('invaliduser');
2488             }
2489         }
2491         if (!empty($useridfrom)) {
2492             // We use get_user here because the from user can be the noreply or support user.
2493             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2494         }
2496         // Check if the current user is the sender/receiver or just a privileged user.
2497         if ($useridto != $USER->id and $useridfrom != $USER->id and
2498             // The deleteanymessage cap seems more reasonable here than readallmessages.
2499              !has_capability('moodle/site:deleteanymessage', $context)) {
2500             throw new moodle_exception('accessdenied', 'admin');
2501         }
2503         if ($useridfrom) {
2504             if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
2505                 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
2506             }
2507         } else {
2508             \core_message\api::mark_all_messages_as_read($useridto);
2509         }
2511         return true;
2512     }
2514     /**
2515      * Mark all notifications as read return description.
2516      *
2517      * @return external_single_structure
2518      * @since 3.2
2519      */
2520     public static function mark_all_messages_as_read_returns() {
2521         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2522     }
2524     /**
2525      * Returns description of method parameters.
2526      *
2527      * @return external_function_parameters
2528      * @since 3.2
2529      */
2530     public static function delete_conversation_parameters() {
2531         return new external_function_parameters(
2532             array(
2533                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
2534                 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
2535             )
2536         );
2537     }
2539     /**
2540      * Deletes a conversation.
2541      *
2542      * @param int $userid The user id of who we want to delete the conversation for
2543      * @param int $otheruserid The user id of the other user in the conversation
2544      * @return array
2545      * @throws moodle_exception
2546      * @since 3.2
2547      */
2548     public static function delete_conversation($userid, $otheruserid) {
2549         global $CFG;
2551         // Check if private messaging between users is allowed.
2552         if (empty($CFG->messaging)) {
2553             throw new moodle_exception('disabled', 'message');
2554         }
2556         // Warnings array, it can be empty at the end but is mandatory.
2557         $warnings = array();
2559         // Validate params.
2560         $params = array(
2561             'userid' => $userid,
2562             'otheruserid' => $otheruserid,
2563         );
2564         $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
2566         // Validate context.
2567         $context = context_system::instance();
2568         self::validate_context($context);
2570         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2571         core_user::require_active_user($user);
2573         if (\core_message\api::can_delete_conversation($user->id)) {
2574             $status = \core_message\api::delete_conversation($user->id, $otheruserid);
2575         } else {
2576             throw new moodle_exception('You do not have permission to delete messages');
2577         }
2579         $results = array(
2580             'status' => $status,
2581             'warnings' => $warnings
2582         );
2584         return $results;
2585     }
2587     /**
2588      * Returns description of method result value.
2589      *
2590      * @return external_description
2591      * @since 3.2
2592      */
2593     public static function delete_conversation_returns() {
2594         return new external_single_structure(
2595             array(
2596                 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
2597                 'warnings' => new external_warnings()
2598             )
2599         );
2600     }
2602     /**
2603      * Returns description of method parameters
2604      *
2605      * @return external_function_parameters
2606      * @since 3.1
2607      */
2608     public static function delete_message_parameters() {
2609         return new external_function_parameters(
2610             array(
2611                 'messageid' => new external_value(PARAM_INT, 'The message id'),
2612                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
2613                 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
2614             )
2615         );
2616     }
2618     /**
2619      * Deletes a message
2620      *
2621      * @param  int $messageid the message id
2622      * @param  int $userid the user id of who we want to delete the message for
2623      * @param  bool $read if is a message read (default to true)
2624      * @return external_description
2625      * @throws moodle_exception
2626      * @since 3.1
2627      */
2628     public static function delete_message($messageid, $userid, $read = true) {
2629         global $CFG;
2631         // Check if private messaging between users is allowed.
2632         if (empty($CFG->messaging)) {
2633             throw new moodle_exception('disabled', 'message');
2634         }
2636         // Warnings array, it can be empty at the end but is mandatory.
2637         $warnings = array();
2639         // Validate params.
2640         $params = array(
2641             'messageid' => $messageid,
2642             'userid' => $userid,
2643             'read' => $read
2644         );
2645         $params = self::validate_parameters(self::delete_message_parameters(), $params);
2647         // Validate context.
2648         $context = context_system::instance();
2649         self::validate_context($context);
2651         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2652         core_user::require_active_user($user);
2654         if (\core_message\api::can_delete_message($user->id, $messageid)) {
2655             $status = \core_message\api::delete_message($user->id, $messageid);
2656         } else {
2657             throw new moodle_exception('You do not have permission to delete this message');
2658         }
2660         $results = array(
2661             'status' => $status,
2662             'warnings' => $warnings
2663         );
2664         return $results;
2665     }
2667     /**
2668      * Returns description of method result value
2669      *
2670      * @return external_description
2671      * @since 3.1
2672      */
2673     public static function delete_message_returns() {
2674         return new external_single_structure(
2675             array(
2676                 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
2677                 'warnings' => new external_warnings()
2678             )
2679         );
2680     }
2682     /**
2683      * Returns description of method parameters
2684      *
2685      * @return external_function_parameters
2686      * @since 3.2
2687      */
2688     public static function message_processor_config_form_parameters() {
2689         return new external_function_parameters(
2690             array(
2691                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
2692                 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
2693                 'formvalues' => new external_multiple_structure(
2694                     new external_single_structure(
2695                         array(
2696                             'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
2697                             'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
2698                         )
2699                     ),
2700                     'Config form values',
2701                     VALUE_REQUIRED
2702                 ),
2703             )
2704         );
2705     }
2707     /**
2708      * Processes a message processor config form.
2709      *
2710      * @param  int $userid the user id
2711      * @param  string $name the name of the processor
2712      * @param  array $formvalues the form values
2713      * @return external_description
2714      * @throws moodle_exception
2715      * @since 3.2
2716      */
2717     public static function message_processor_config_form($userid, $name, $formvalues) {
2718         global $USER, $CFG;
2720         // Check if messaging is enabled.
2721         if (empty($CFG->messaging)) {
2722             throw new moodle_exception('disabled', 'message');
2723         }
2725         $params = self::validate_parameters(
2726             self::message_processor_config_form_parameters(),
2727             array(
2728                 'userid' => $userid,
2729                 'name' => $name,
2730                 'formvalues' => $formvalues,
2731             )
2732         );
2734         $user = self::validate_preferences_permissions($params['userid']);
2736         $processor = get_message_processor($name);
2737         $preferences = [];
2738         $form = new stdClass();
2740         foreach ($formvalues as $formvalue) {
2741             // Curly braces to ensure interpretation is consistent between
2742             // php 5 and php 7.
2743             $form->{$formvalue['name']} = $formvalue['value'];
2744         }
2746         $processor->process_form($form, $preferences);
2748         if (!empty($preferences)) {
2749             set_user_preferences($preferences, $userid);
2750         }
2751     }
2753     /**
2754      * Returns description of method result value
2755      *
2756      * @return external_description
2757      * @since 3.2
2758      */
2759     public static function message_processor_config_form_returns() {
2760         return null;
2761     }
2763     /**
2764      * Returns description of method parameters
2765      *
2766      * @return external_function_parameters
2767      * @since 3.2
2768      */
2769     public static function get_message_processor_parameters() {
2770         return new external_function_parameters(
2771             array(
2772                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
2773                 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
2774             )
2775         );
2776     }
2778     /**
2779      * Get a message processor.
2780      *
2781      * @param int $userid
2782      * @param string $name the name of the processor
2783      * @return external_description
2784      * @throws moodle_exception
2785      * @since 3.2
2786      */
2787     public static function get_message_processor($userid = 0, $name) {
2788         global $USER, $PAGE, $CFG;
2790         // Check if messaging is enabled.
2791         if (empty($CFG->messaging)) {
2792             throw new moodle_exception('disabled', 'message');
2793         }
2795         $params = self::validate_parameters(
2796             self::get_message_processor_parameters(),
2797             array(
2798                 'userid' => $userid,
2799                 'name' => $name,
2800             )
2801         );
2803         if (empty($params['userid'])) {
2804             $params['userid'] = $USER->id;
2805         }
2807         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2808         core_user::require_active_user($user);
2809         self::validate_context(context_user::instance($params['userid']));
2811         $processor = get_message_processor($name);
2813         $processoroutput = new \core_message\output\processor($processor, $user);
2814         $renderer = $PAGE->get_renderer('core_message');
2816         return $processoroutput->export_for_template($renderer);
2817     }
2819     /**
2820      * Returns description of method result value
2821      *
2822      * @return external_description
2823      * @since 3.2
2824      */
2825     public static function get_message_processor_returns() {
2826         return new external_function_parameters(
2827             array(
2828                 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
2829                 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
2830             )
2831         );
2832     }
2834     /**
2835      * Check that the user has enough permission to retrieve message or notifications preferences.
2836      *
2837      * @param  int $userid the user id requesting the preferences
2838      * @return stdClass full user object
2839      * @throws moodle_exception
2840      * @since  Moodle 3.2
2841      */
2842     protected static function validate_preferences_permissions($userid) {
2843         global $USER;
2845         if (empty($userid)) {
2846             $user = $USER;
2847         } else {
2848             $user = core_user::get_user($userid, '*', MUST_EXIST);
2849             core_user::require_active_user($user);
2850         }
2852         $systemcontext = context_system::instance();
2853         self::validate_context($systemcontext);
2855         // Check access control.
2856         if ($user->id == $USER->id) {
2857             // Editing own message profile.
2858             require_capability('moodle/user:editownmessageprofile', $systemcontext);
2859         } else {
2860             // Teachers, parents, etc.
2861             $personalcontext = context_user::instance($user->id);
2862             require_capability('moodle/user:editmessageprofile', $personalcontext);
2863         }
2864         return $user;
2865     }
2867     /**
2868      * Returns a notification or message preference structure.
2869      *
2870      * @return external_single_structure the structure
2871      * @since  Moodle 3.2
2872      */
2873     protected static function get_preferences_structure() {
2874         return new external_single_structure(
2875             array(
2876                 'userid' => new external_value(PARAM_INT, 'User id'),
2877                 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
2878                 'processors' => new external_multiple_structure(
2879                     new external_single_structure(
2880                         array(
2881                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2882                             'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2883                             'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
2884                             'contextid' => new external_value(PARAM_INT, 'Context id'),
2885                             'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
2886                         )
2887                     ),
2888                     'Config form values'
2889                 ),
2890                 'components' => new external_multiple_structure(
2891                     new external_single_structure(
2892                         array(
2893                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2894                             'notifications' => new external_multiple_structure(
2895                                 new external_single_structure(
2896                                     array(
2897                                         'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2898                                         'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
2899                                         'processors' => new external_multiple_structure(
2900                                             new external_single_structure(
2901                                                 array(
2902                                                     'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2903                                                     'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2904                                                     'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
2905                                                     'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
2906                                                     'loggedin' => new external_single_structure(
2907                                                         array(
2908                                                             'name' => new external_value(PARAM_NOTAGS, 'Name'),
2909                                                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2910                                                             'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2911                                                         )
2912                                                     ),
2913                                                     'loggedoff' => new external_single_structure(
2914                                                         array(
2915                                                             'name' => new external_value(PARAM_NOTAGS, 'Name'),
2916                                                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2917                                                             'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2918                                                         )
2919                                                     ),
2920                                                 )
2921                                             ),
2922                                             'Processors values for this notification'
2923                                         ),
2924                                     )
2925                                 ),
2926                                 'List of notificaitons for the component'
2927                             ),
2928                         )
2929                     ),
2930                     'Available components'
2931                 ),
2932             )
2933         );
2934     }
2936     /**
2937      * Returns description of method parameters
2938      *
2939      * @return external_function_parameters
2940      * @since 3.2
2941      */
2942     public static function get_user_notification_preferences_parameters() {
2943         return new external_function_parameters(
2944             array(
2945                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
2946             )
2947         );
2948     }
2950     /**
2951      * Get the notification preferences for a given user.
2952      *
2953      * @param int $userid id of the user, 0 for current user
2954      * @return external_description
2955      * @throws moodle_exception
2956      * @since 3.2
2957      */
2958     public static function get_user_notification_preferences($userid = 0) {
2959         global $PAGE;
2961         $params = self::validate_parameters(
2962             self::get_user_notification_preferences_parameters(),
2963             array(
2964                 'userid' => $userid,
2965             )
2966         );
2967         $user = self::validate_preferences_permissions($params['userid']);
2969         $processors = get_message_processors();
2970         $providers = message_get_providers_for_user($user->id);
2971         $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2972         $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
2974         $renderer = $PAGE->get_renderer('core_message');
2976         $result = array(
2977             'warnings' => array(),
2978             'preferences' => $notificationlist->export_for_template($renderer)
2979         );
2980         return $result;
2981     }
2983     /**
2984      * Returns description of method result value
2985      *
2986      * @return external_description
2987      * @since 3.2
2988      */
2989     public static function get_user_notification_preferences_returns() {
2990         return new external_function_parameters(
2991             array(
2992                 'preferences' => self::get_preferences_structure(),
2993                 'warnings' => new external_warnings(),
2994             )
2995         );
2996     }
2999     /**
3000      * Returns description of method parameters
3001      *
3002      * @return external_function_parameters
3003      * @since 3.2
3004      */
3005     public static function get_user_message_preferences_parameters() {
3006         return new external_function_parameters(
3007             array(
3008                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
3009             )
3010         );
3011     }
3013     /**
3014      * Get the notification preferences for a given user.
3015      *
3016      * @param int $userid id of the user, 0 for current user
3017      * @return external_description
3018      * @throws moodle_exception
3019      * @since 3.2
3020      */
3021     public static function get_user_message_preferences($userid = 0) {
3022         global $PAGE;
3024         $params = self::validate_parameters(
3025             self::get_user_message_preferences_parameters(),
3026             array(
3027                 'userid' => $userid,
3028             )
3029         );
3031         $user = self::validate_preferences_permissions($params['userid']);
3033         // Filter out enabled, available system_configured and user_configured processors only.
3034         $readyprocessors = array_filter(get_message_processors(), function($processor) {
3035             return $processor->enabled &&
3036                 $processor->configured &&
3037                 $processor->object->is_user_configured() &&
3038                 // Filter out processors that don't have and message preferences to configure.
3039                 $processor->object->has_message_preferences();
3040         });
3042         $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
3043             return $provider->component === 'moodle';
3044         });
3045         $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
3046         $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
3047             $providers, $preferences, $user);
3049         $renderer = $PAGE->get_renderer('core_message');
3051         $result = array(
3052             'warnings' => array(),
3053             'preferences' => $notificationlistoutput->export_for_template($renderer),
3054             'blocknoncontacts' => get_user_preferences('message_blocknoncontacts', '', $user->id) ? true : false,
3055         );
3056         return $result;
3057     }
3059     /**
3060      * Returns description of method result value
3061      *
3062      * @return external_description
3063      * @since 3.2
3064      */
3065     public static function get_user_message_preferences_returns() {
3066         return new external_function_parameters(
3067             array(
3068                 'preferences' => self::get_preferences_structure(),
3069                 'blocknoncontacts' => new external_value(PARAM_BOOL, 'Whether to block or not messages from non contacts'),
3070                 'warnings' => new external_warnings(),
3071             )
3072         );
3073     }