MDL-63214 message: Add privacy preferences to filter who can message
[moodle.git] / message / externallib.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * External message API
20  *
21  * @package    core_message
22  * @category   external
23  * @copyright  2011 Jerome Mouneyrac
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 defined('MOODLE_INTERNAL') || die();
29 require_once("$CFG->libdir/externallib.php");
30 require_once($CFG->dirroot . "/message/lib.php");
32 /**
33  * Message external functions
34  *
35  * @package    core_message
36  * @category   external
37  * @copyright  2011 Jerome Mouneyrac
38  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  * @since Moodle 2.2
40  */
41 class core_message_external extends external_api {
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);
94         $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
96         $resultmessages = array();
97         foreach ($params['messages'] as $message) {
98             $resultmsg = array(); //the infos about the success of the operation
100             // We are going to do some checking.
101             // Code should match /messages/index.php checks.
102             $success = true;
104             // Check the user exists.
105             if (empty($tousers[$message['touserid']])) {
106                 $success = false;
107                 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
108             }
110             // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
111             // Check if the recipient can be messaged by the sender.
112             if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
113                 $success = false;
114                 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
115             }
117             // Now we can send the message (at least try).
118             if ($success) {
119                 // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object.
120                 $success = message_post_message($USER, $tousers[$message['touserid']],
121                         $message['text'], external_validate_format($message['textformat']));
122             }
124             // Build the resultmsg.
125             if (isset($message['clientmsgid'])) {
126                 $resultmsg['clientmsgid'] = $message['clientmsgid'];
127             }
128             if ($success) {
129                 $resultmsg['msgid'] = $success;
130             } else {
131                 // WARNINGS: for backward compatibility we return this errormessage.
132                 //          We should have thrown exceptions as these errors prevent results to be returned.
133                 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
134                 $resultmsg['msgid'] = -1;
135                 $resultmsg['errormessage'] = $errormessage;
136             }
138             $resultmessages[] = $resultmsg;
139         }
141         return $resultmessages;
142     }
144     /**
145      * Returns description of method result value
146      *
147      * @return external_description
148      * @since Moodle 2.2
149      */
150     public static function send_instant_messages_returns() {
151         return new external_multiple_structure(
152             new external_single_structure(
153                 array(
154                     'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds:  id of the created message if it succeeded, -1 when failed'),
155                     'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
156                     'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL)
157                 )
158             )
159         );
160     }
162     /**
163      * Create contacts parameters description.
164      *
165      * @deprecated since Moodle 3.6
166      * @return external_function_parameters
167      * @since Moodle 2.5
168      */
169     public static function create_contacts_parameters() {
170         return new external_function_parameters(
171             array(
172                 'userids' => new external_multiple_structure(
173                     new external_value(PARAM_INT, 'User ID'),
174                     'List of user IDs'
175                 ),
176                 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
177                     current user', VALUE_DEFAULT, 0)
178             )
179         );
180     }
182     /**
183      * Create contacts.
184      *
185      * @deprecated since Moodle 3.6
186      * @param array $userids array of user IDs.
187      * @param int $userid The id of the user we are creating the contacts for
188      * @return external_description
189      * @since Moodle 2.5
190      */
191     public static function create_contacts($userids, $userid = 0) {
192         global $CFG, $USER;
194         // Check if messaging is enabled.
195         if (empty($CFG->messaging)) {
196             throw new moodle_exception('disabled', 'message');
197         }
199         if (empty($userid)) {
200             $userid = $USER->id;
201         }
203         // Validate context.
204         $context = context_system::instance();
205         self::validate_context($context);
207         $capability = 'moodle/site:manageallmessaging';
208         if (($USER->id != $userid) && !has_capability($capability, $context)) {
209             throw new required_capability_exception($context, $capability, 'nopermissions', '');
210         }
212         $params = array('userids' => $userids, 'userid' => $userid);
213         $params = self::validate_parameters(self::create_contacts_parameters(), $params);
215         $warnings = array();
216         foreach ($params['userids'] as $id) {
217             if (!message_add_contact($id, 0, $userid)) {
218                 $warnings[] = array(
219                     'item' => 'user',
220                     'itemid' => $id,
221                     'warningcode' => 'contactnotcreated',
222                     'message' => 'The contact could not be created'
223                 );
224             }
225         }
226         return $warnings;
227     }
229     /**
230      * Create contacts return description.
231      *
232      * @deprecated since Moodle 3.6
233      * @return external_description
234      * @since Moodle 2.5
235      */
236     public static function create_contacts_returns() {
237         return new external_warnings();
238     }
240     /**
241      * Marking the method as deprecated.
242      *
243      * @return bool
244      */
245     public static function create_contacts_is_deprecated() {
246         return true;
247     }
249     /**
250      * Delete contacts parameters description.
251      *
252      * @return external_function_parameters
253      * @since Moodle 2.5
254      */
255     public static function delete_contacts_parameters() {
256         return new external_function_parameters(
257             array(
258                 'userids' => new external_multiple_structure(
259                     new external_value(PARAM_INT, 'User ID'),
260                     'List of user IDs'
261                 ),
262                 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
263                     current user', VALUE_DEFAULT, 0)
264             )
265         );
266     }
268     /**
269      * Delete contacts.
270      *
271      * @param array $userids array of user IDs.
272      * @param int $userid The id of the user we are deleting the contacts for
273      * @return null
274      * @since Moodle 2.5
275      */
276     public static function delete_contacts($userids, $userid = 0) {
277         global $CFG, $USER;
279         // Check if messaging is enabled.
280         if (empty($CFG->messaging)) {
281             throw new moodle_exception('disabled', 'message');
282         }
284         if (empty($userid)) {
285             $userid = $USER->id;
286         }
288         // Validate context.
289         $context = context_system::instance();
290         self::validate_context($context);
292         $capability = 'moodle/site:manageallmessaging';
293         if (($USER->id != $userid) && !has_capability($capability, $context)) {
294             throw new required_capability_exception($context, $capability, 'nopermissions', '');
295         }
297         $params = array('userids' => $userids, 'userid' => $userid);
298         $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
300         foreach ($params['userids'] as $id) {
301             \core_message\api::remove_contact($userid, $id);
302         }
304         return null;
305     }
307     /**
308      * Delete contacts return description.
309      *
310      * @return external_description
311      * @since Moodle 2.5
312      */
313     public static function delete_contacts_returns() {
314         return null;
315     }
317     /**
318      * Block user parameters description.
319      *
320      * @return external_function_parameters
321      */
322     public static function block_user_parameters() {
323         return new external_function_parameters(
324             [
325                 'userid' => new external_value(PARAM_INT, 'The id of the user who is blocking'),
326                 'blockeduserid' => new external_value(PARAM_INT, 'The id of the user being blocked'),
327             ]
328         );
329     }
331     /**
332      * Blocks a user.
333      *
334      * @param int $userid The id of the user who is blocking
335      * @param int $blockeduserid The id of the user being blocked
336      * @return external_description
337      */
338     public static function block_user(int $userid, int $blockeduserid) {
339         global $CFG, $USER;
341         // Check if messaging is enabled.
342         if (empty($CFG->messaging)) {
343             throw new moodle_exception('disabled', 'message');
344         }
346         // Validate context.
347         $context = context_system::instance();
348         self::validate_context($context);
350         $capability = 'moodle/site:manageallmessaging';
351         if (($USER->id != $userid) && !has_capability($capability, $context)) {
352             throw new required_capability_exception($context, $capability, 'nopermissions', '');
353         }
355         $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
356         $params = self::validate_parameters(self::block_user_parameters(), $params);
358         if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
359             \core_message\api::block_user($params['userid'], $params['blockeduserid']);
360         }
362         return [];
363     }
365     /**
366      * Block user return description.
367      *
368      * @return external_description
369      */
370     public static function block_user_returns() {
371         return new external_warnings();
372     }
374     /**
375      * Unblock user parameters description.
376      *
377      * @return external_function_parameters
378      */
379     public static function unblock_user_parameters() {
380         return new external_function_parameters(
381             [
382                 'userid' => new external_value(PARAM_INT, 'The id of the user who is unblocking'),
383                 'unblockeduserid' => new external_value(PARAM_INT, 'The id of the user being unblocked'),
384             ]
385         );
386     }
388     /**
389      * Unblock user.
390      *
391      * @param int $userid The id of the user who is unblocking
392      * @param int $unblockeduserid The id of the user being unblocked
393      */
394     public static function unblock_user(int $userid, int $unblockeduserid) {
395         global $CFG, $USER;
397         // Check if messaging is enabled.
398         if (empty($CFG->messaging)) {
399             throw new moodle_exception('disabled', 'message');
400         }
402         // Validate context.
403         $context = context_system::instance();
404         self::validate_context($context);
406         $capability = 'moodle/site:manageallmessaging';
407         if (($USER->id != $userid) && !has_capability($capability, $context)) {
408             throw new required_capability_exception($context, $capability, 'nopermissions', '');
409         }
411         $params = ['userid' => $userid, 'unblockeduserid' => $unblockeduserid];
412         $params = self::validate_parameters(self::unblock_user_parameters(), $params);
414         \core_message\api::unblock_user($params['userid'], $params['unblockeduserid']);
416         return [];
417     }
419     /**
420      * Unblock user return description.
421      *
422      * @return external_description
423      */
424     public static function unblock_user_returns() {
425         return new external_warnings();
426     }
428     /**
429      * Block contacts parameters description.
430      *
431      * @deprecated since Moodle 3.6
432      * @return external_function_parameters
433      * @since Moodle 2.5
434      */
435     public static function block_contacts_parameters() {
436         return new external_function_parameters(
437             array(
438                 'userids' => new external_multiple_structure(
439                     new external_value(PARAM_INT, 'User ID'),
440                     'List of user IDs'
441                 ),
442                 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
443                     current user', VALUE_DEFAULT, 0)
444             )
445         );
446     }
448     /**
449      * Block contacts.
450      *
451      * @deprecated since Moodle 3.6
452      * @param array $userids array of user IDs.
453      * @param int $userid The id of the user we are blocking the contacts for
454      * @return external_description
455      * @since Moodle 2.5
456      */
457     public static function block_contacts($userids, $userid = 0) {
458         global $CFG, $USER;
460         // Check if messaging is enabled.
461         if (empty($CFG->messaging)) {
462             throw new moodle_exception('disabled', 'message');
463         }
465         if (empty($userid)) {
466             $userid = $USER->id;
467         }
469         // Validate context.
470         $context = context_system::instance();
471         self::validate_context($context);
473         $capability = 'moodle/site:manageallmessaging';
474         if (($USER->id != $userid) && !has_capability($capability, $context)) {
475             throw new required_capability_exception($context, $capability, 'nopermissions', '');
476         }
478         $params = array('userids' => $userids, 'userid' => $userid);
479         $params = self::validate_parameters(self::block_contacts_parameters(), $params);
481         $warnings = array();
482         foreach ($params['userids'] as $id) {
483             if (!message_block_contact($id, $userid)) {
484                 $warnings[] = array(
485                     'item' => 'user',
486                     'itemid' => $id,
487                     'warningcode' => 'contactnotblocked',
488                     'message' => 'The contact could not be blocked'
489                 );
490             }
491         }
492         return $warnings;
493     }
495     /**
496      * Block contacts return description.
497      *
498      * @deprecated since Moodle 3.6
499      * @return external_description
500      * @since Moodle 2.5
501      */
502     public static function block_contacts_returns() {
503         return new external_warnings();
504     }
506     /**
507      * Marking the method as deprecated.
508      *
509      * @return bool
510      */
511     public static function block_contacts_is_deprecated() {
512         return true;
513     }
515     /**
516      * Unblock contacts parameters description.
517      *
518      * @deprecated since Moodle 3.6
519      * @return external_function_parameters
520      * @since Moodle 2.5
521      */
522     public static function unblock_contacts_parameters() {
523         return new external_function_parameters(
524             array(
525                 'userids' => new external_multiple_structure(
526                     new external_value(PARAM_INT, 'User ID'),
527                     'List of user IDs'
528                 ),
529                 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
530                     current user', VALUE_DEFAULT, 0)
531             )
532         );
533     }
535     /**
536      * Unblock contacts.
537      *
538      * @param array $userids array of user IDs.
539      * @param int $userid The id of the user we are unblocking the contacts for
540      * @return null
541      * @since Moodle 2.5
542      */
543     public static function unblock_contacts($userids, $userid = 0) {
544         global $CFG, $USER;
546         // Check if messaging is enabled.
547         if (empty($CFG->messaging)) {
548             throw new moodle_exception('disabled', 'message');
549         }
551         if (empty($userid)) {
552             $userid = $USER->id;
553         }
555         // Validate context.
556         $context = context_system::instance();
557         self::validate_context($context);
559         $capability = 'moodle/site:manageallmessaging';
560         if (($USER->id != $userid) && !has_capability($capability, $context)) {
561             throw new required_capability_exception($context, $capability, 'nopermissions', '');
562         }
564         $params = array('userids' => $userids, 'userid' => $userid);
565         $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
567         foreach ($params['userids'] as $id) {
568             message_unblock_contact($id, $userid);
569         }
571         return null;
572     }
574     /**
575      * Unblock contacts return description.
576      *
577      * @deprecated since Moodle 3.6
578      * @return external_description
579      * @since Moodle 2.5
580      */
581     public static function unblock_contacts_returns() {
582         return null;
583     }
585     /**
586      * Marking the method as deprecated.
587      *
588      * @return bool
589      */
590     public static function unblock_contacts_is_deprecated() {
591         return true;
592     }
594     /**
595      * Returns contact requests parameters description.
596      *
597      * @return external_function_parameters
598      */
599     public static function get_contact_requests_parameters() {
600         return new external_function_parameters(
601             [
602                 'userid' => new external_value(PARAM_INT, 'The id of the user we want the requests for')
603             ]
604         );
605     }
607     /**
608      * Handles returning the contact requests for a user.
609      *
610      * This also includes the user data necessary to display information
611      * about the user.
612      *
613      * It will not include blocked users.
614      *
615      * @param int $userid The id of the user we want to get the contact requests for
616      */
617     public static function get_contact_requests(int $userid) {
618         global $CFG, $USER;
620         // Check if messaging is enabled.
621         if (empty($CFG->messaging)) {
622             throw new moodle_exception('disabled', 'message');
623         }
625         // Validate context.
626         $context = context_system::instance();
627         self::validate_context($context);
629         $capability = 'moodle/site:manageallmessaging';
630         if (($USER->id != $userid) && !has_capability($capability, $context)) {
631             throw new required_capability_exception($context, $capability, 'nopermissions', '');
632         }
634         $params = ['userid' => $userid];
635         $params = self::validate_parameters(self::get_contact_requests_parameters(), $params);
637         return \core_message\api::get_contact_requests($params['userid']);
638     }
640     /**
641      * Returns the contact requests return description.
642      *
643      * @return external_description
644      */
645     public static function get_contact_requests_returns() {
646         return new external_multiple_structure(
647             new external_single_structure(
648                 [
649                     'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'),
650                     'contactrequestid' => new external_value(PARAM_INT, 'The ID of the contact request'),
651                     'picture' => new external_value(core_user::get_property_type('picture'), 'The picture'),
652                     'firstname' => new external_value(core_user::get_property_type('firstname'),
653                         'The first name(s) of the user'),
654                     'lastname' => new external_value(core_user::get_property_type('lastname'),
655                         'The family name of the user'),
656                     'firstnamephonetic' => new external_value(core_user::get_property_type('firstnamephonetic'),
657                         'The phonetic first name of the user'),
658                     'lastnamephonetic' => new external_value(core_user::get_property_type('lastnamephonetic'),
659                         'The phonetic last name of the user'),
660                     'middlename' => new external_value(core_user::get_property_type('middlename'),
661                         'The middle name of the user'),
662                     'alternatename' => new external_value(core_user::get_property_type('alternatename'),
663                         'The alternate name of the user'),
664                     'email' => new external_value(core_user::get_property_type('email'), 'An email address')
665                 ]
666             )
667         );
668     }
670     /**
671      * Creates a contact request parameters description.
672      *
673      * @return external_function_parameters
674      */
675     public static function create_contact_request_parameters() {
676         return new external_function_parameters(
677             [
678                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
679                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
680             ]
681         );
682     }
684     /**
685      * Creates a contact request.
686      *
687      * @param int $userid The id of the user who is creating the contact request
688      * @param int $requesteduserid The id of the user being requested
689      */
690     public static function create_contact_request(int $userid, int $requesteduserid) {
691         global $CFG, $USER;
693         // Check if messaging is enabled.
694         if (empty($CFG->messaging)) {
695             throw new moodle_exception('disabled', 'message');
696         }
698         // Validate context.
699         $context = context_system::instance();
700         self::validate_context($context);
702         $capability = 'moodle/site:manageallmessaging';
703         if (($USER->id != $userid) && !has_capability($capability, $context)) {
704             throw new required_capability_exception($context, $capability, 'nopermissions', '');
705         }
707         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
708         $params = self::validate_parameters(self::create_contact_request_parameters(), $params);
710         if (!\core_message\api::can_create_contact($params['userid'], $params['requesteduserid'])) {
711             $warning[] = [
712                 'item' => 'user',
713                 'itemid' => $params['requesteduserid'],
714                 'warningcode' => 'cannotcreatecontactrequest',
715                 'message' => 'You are unable to create a contact request for this user'
716             ];
717             return $warning;
718         }
720         if (!\core_message\api::does_contact_request_exist($params['userid'], $params['requesteduserid'])) {
721             \core_message\api::create_contact_request($params['userid'], $params['requesteduserid']);
722         }
724         return [];
725     }
727     /**
728      * Creates a contact request return description.
729      *
730      * @return external_description
731      */
732     public static function create_contact_request_returns() {
733         return new external_warnings();
734     }
736     /**
737      * Confirm a contact request parameters description.
738      *
739      * @return external_function_parameters
740      */
741     public static function confirm_contact_request_parameters() {
742         return new external_function_parameters(
743             [
744                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
745                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
746             ]
747         );
748     }
750     /**
751      * Confirm a contact request.
752      *
753      * @param int $userid The id of the user who is creating the contact request
754      * @param int $requesteduserid The id of the user being requested
755      */
756     public static function confirm_contact_request(int $userid, int $requesteduserid) {
757         global $CFG, $USER;
759         // Check if messaging is enabled.
760         if (empty($CFG->messaging)) {
761             throw new moodle_exception('disabled', 'message');
762         }
764         // Validate context.
765         $context = context_system::instance();
766         self::validate_context($context);
768         $capability = 'moodle/site:manageallmessaging';
769         if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
770             throw new required_capability_exception($context, $capability, 'nopermissions', '');
771         }
773         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
774         $params = self::validate_parameters(self::confirm_contact_request_parameters(), $params);
776         \core_message\api::confirm_contact_request($params['userid'], $params['requesteduserid']);
778         return [];
779     }
781     /**
782      * Confirm a contact request return description.
783      *
784      * @return external_description
785      */
786     public static function confirm_contact_request_returns() {
787         return new external_warnings();
788     }
790     /**
791      * Declines a contact request parameters description.
792      *
793      * @return external_function_parameters
794      */
795     public static function decline_contact_request_parameters() {
796         return new external_function_parameters(
797             [
798                 'userid' => new external_value(PARAM_INT, 'The id of the user making the request'),
799                 'requesteduserid' => new external_value(PARAM_INT, 'The id of the user being requested')
800             ]
801         );
802     }
804     /**
805      * Declines a contact request.
806      *
807      * @param int $userid The id of the user who is creating the contact request
808      * @param int $requesteduserid The id of the user being requested
809      */
810     public static function decline_contact_request(int $userid, int $requesteduserid) {
811         global $CFG, $USER;
813         // Check if messaging is enabled.
814         if (empty($CFG->messaging)) {
815             throw new moodle_exception('disabled', 'message');
816         }
818         // Validate context.
819         $context = context_system::instance();
820         self::validate_context($context);
822         $capability = 'moodle/site:manageallmessaging';
823         if (($USER->id != $requesteduserid) && !has_capability($capability, $context)) {
824             throw new required_capability_exception($context, $capability, 'nopermissions', '');
825         }
827         $params = ['userid' => $userid, 'requesteduserid' => $requesteduserid];
828         $params = self::validate_parameters(self::decline_contact_request_parameters(), $params);
830         \core_message\api::decline_contact_request($params['userid'], $params['requesteduserid']);
832         return [];
833     }
835     /**
836      * Declines a contact request return description.
837      *
838      * @return external_description
839      */
840     public static function decline_contact_request_returns() {
841         return new external_warnings();
842     }
844     /**
845      * Return the structure of a message area contact.
846      *
847      * @return external_single_structure
848      * @since Moodle 3.2
849      */
850     private static function get_messagearea_contact_structure() {
851         return new external_single_structure(
852             array(
853                 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
854                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
855                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
856                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
857                 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
858                 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
859                 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
860                 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
861                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
862                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
863                 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
864                 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
865                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
866                     VALUE_DEFAULT, null),
867             )
868         );
869     }
871     /**
872      * Return the structure of a message area message.
873      *
874      * @return external_single_structure
875      * @since Moodle 3.2
876      */
877     private static function get_messagearea_message_structure() {
878         return new external_single_structure(
879             array(
880                 'id' => new external_value(PARAM_INT, 'The id of the message'),
881                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
882                 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
883                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
884                 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
885                 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
886                 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
887                 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
888                 'timecreated' => new external_value(PARAM_INT, 'The timecreated timestamp for the message'),
889                 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
890             )
891         );
892     }
894     /**
895      * Get messagearea search users in course parameters.
896      *
897      * @return external_function_parameters
898      * @since 3.2
899      */
900     public static function data_for_messagearea_search_users_in_course_parameters() {
901         return new external_function_parameters(
902             array(
903                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
904                 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
905                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
906                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
907                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
908             )
909         );
910     }
912     /**
913      * Get messagearea search users in course results.
914      *
915      * @param int $userid The id of the user who is performing the search
916      * @param int $courseid The id of the course
917      * @param string $search The string being searched
918      * @param int $limitfrom
919      * @param int $limitnum
920      * @return stdClass
921      * @throws moodle_exception
922      * @since 3.2
923      */
924     public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
925                                                                        $limitnum = 0) {
926         global $CFG, $PAGE, $USER;
928         // Check if messaging is enabled.
929         if (empty($CFG->messaging)) {
930             throw new moodle_exception('disabled', 'message');
931         }
933         $systemcontext = context_system::instance();
935         $params = array(
936             'userid' => $userid,
937             'courseid' => $courseid,
938             'search' => $search,
939             'limitfrom' => $limitfrom,
940             'limitnum' => $limitnum
941         );
942         self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
943         self::validate_context($systemcontext);
945         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
946             throw new moodle_exception('You do not have permission to perform this action.');
947         }
949         $users = \core_message\api::search_users_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
950         $results = new \core_message\output\messagearea\user_search_results($users);
952         $renderer = $PAGE->get_renderer('core_message');
953         return $results->export_for_template($renderer);
954     }
956     /**
957      * Get messagearea search users in course returns.
958      *
959      * @return external_single_structure
960      * @since 3.2
961      */
962     public static function data_for_messagearea_search_users_in_course_returns() {
963         return new external_single_structure(
964             array(
965                 'contacts' => new external_multiple_structure(
966                     self::get_messagearea_contact_structure()
967                 ),
968             )
969         );
970     }
972     /**
973      * Get messagearea search users parameters.
974      *
975      * @return external_function_parameters
976      * @since 3.2
977      */
978     public static function data_for_messagearea_search_users_parameters() {
979         return new external_function_parameters(
980             array(
981                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
982                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
983                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
984             )
985         );
986     }
988     /**
989      * Get messagearea search users results.
990      *
991      * @param int $userid The id of the user who is performing the search
992      * @param string $search The string being searched
993      * @param int $limitnum
994      * @return stdClass
995      * @throws moodle_exception
996      * @since 3.2
997      */
998     public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
999         global $CFG, $PAGE, $USER;
1001         // Check if messaging is enabled.
1002         if (empty($CFG->messaging)) {
1003             throw new moodle_exception('disabled', 'message');
1004         }
1006         $systemcontext = context_system::instance();
1008         $params = array(
1009             'userid' => $userid,
1010             'search' => $search,
1011             'limitnum' => $limitnum
1012         );
1013         self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
1014         self::validate_context($systemcontext);
1016         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1017             throw new moodle_exception('You do not have permission to perform this action.');
1018         }
1020         list($contacts, $courses, $noncontacts) = \core_message\api::search_users($userid, $search, $limitnum);
1021         $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
1023         $renderer = $PAGE->get_renderer('core_message');
1024         return $search->export_for_template($renderer);
1025     }
1027     /**
1028      * Get messagearea search users returns.
1029      *
1030      * @return external_single_structure
1031      * @since 3.2
1032      */
1033     public static function data_for_messagearea_search_users_returns() {
1034         return new external_single_structure(
1035             array(
1036                 'contacts' => new external_multiple_structure(
1037                     self::get_messagearea_contact_structure()
1038                 ),
1039                 'courses' => new external_multiple_structure(
1040                     new external_single_structure(
1041                         array(
1042                             'id' => new external_value(PARAM_INT, 'The course id'),
1043                             'shortname' => new external_value(PARAM_TEXT, 'The course shortname'),
1044                             'fullname' => new external_value(PARAM_TEXT, 'The course fullname'),
1045                         )
1046                     )
1047                 ),
1048                 'noncontacts' => new external_multiple_structure(
1049                     self::get_messagearea_contact_structure()
1050                 )
1051             )
1052         );
1053     }
1055     /**
1056      * Get messagearea search messages parameters.
1057      *
1058      * @return external_function_parameters
1059      * @since 3.2
1060      */
1061     public static function data_for_messagearea_search_messages_parameters() {
1062         return new external_function_parameters(
1063             array(
1064                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
1065                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
1066                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1067                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1068             )
1069         );
1070     }
1072     /**
1073      * Get messagearea search messages results.
1074      *
1075      * @param int $userid The id of the user who is performing the search
1076      * @param string $search The string being searched
1077      * @param int $limitfrom
1078      * @param int $limitnum
1079      * @return stdClass
1080      * @throws moodle_exception
1081      * @since 3.2
1082      */
1083     public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
1084         global $CFG, $PAGE, $USER;
1086         // Check if messaging is enabled.
1087         if (empty($CFG->messaging)) {
1088             throw new moodle_exception('disabled', 'message');
1089         }
1091         $systemcontext = context_system::instance();
1093         $params = array(
1094             'userid' => $userid,
1095             'search' => $search,
1096             'limitfrom' => $limitfrom,
1097             'limitnum' => $limitnum
1099         );
1100         self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
1101         self::validate_context($systemcontext);
1103         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1104             throw new moodle_exception('You do not have permission to perform this action.');
1105         }
1107         $messages = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
1108         $results = new \core_message\output\messagearea\message_search_results($messages);
1110         $renderer = $PAGE->get_renderer('core_message');
1111         return $results->export_for_template($renderer);
1112     }
1114     /**
1115      * Get messagearea search messages returns.
1116      *
1117      * @return external_single_structure
1118      * @since 3.2
1119      */
1120     public static function data_for_messagearea_search_messages_returns() {
1121         return new external_single_structure(
1122             array(
1123                 'contacts' => new external_multiple_structure(
1124                     self::get_messagearea_contact_structure()
1125                 )
1126             )
1127         );
1128     }
1130     /**
1131      * The messagearea conversations parameters.
1132      *
1133      * @return external_function_parameters
1134      * @since 3.2
1135      */
1136     public static function data_for_messagearea_conversations_parameters() {
1137         return new external_function_parameters(
1138             array(
1139                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
1140                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1141                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
1142             )
1143         );
1144     }
1146     /**
1147      * Get messagearea conversations.
1148      *
1149      * @param int $userid The id of the user who we are viewing conversations for
1150      * @param int $limitfrom
1151      * @param int $limitnum
1152      * @return stdClass
1153      * @throws moodle_exception
1154      * @since 3.2
1155      */
1156     public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
1157         global $CFG, $PAGE, $USER;
1159         // Check if messaging is enabled.
1160         if (empty($CFG->messaging)) {
1161             throw new moodle_exception('disabled', 'message');
1162         }
1164         $systemcontext = context_system::instance();
1166         $params = array(
1167             'userid' => $userid,
1168             'limitfrom' => $limitfrom,
1169             'limitnum' => $limitnum
1170         );
1171         self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
1172         self::validate_context($systemcontext);
1174         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1175             throw new moodle_exception('You do not have permission to perform this action.');
1176         }
1178         $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum);
1179         $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
1181         $renderer = $PAGE->get_renderer('core_message');
1182         return $conversations->export_for_template($renderer);
1183     }
1185     /**
1186      * The messagearea conversations return structure.
1187      *
1188      * @return external_single_structure
1189      * @since 3.2
1190      */
1191     public static function data_for_messagearea_conversations_returns() {
1192         return new external_single_structure(
1193             array(
1194                 'contacts' => new external_multiple_structure(
1195                     self::get_messagearea_contact_structure()
1196                 )
1197             )
1198         );
1199     }
1201     /**
1202      * The messagearea contacts return parameters.
1203      *
1204      * @return external_function_parameters
1205      * @since 3.2
1206      */
1207     public static function data_for_messagearea_contacts_parameters() {
1208         return self::data_for_messagearea_conversations_parameters();
1209     }
1211     /**
1212      * Get messagearea contacts parameters.
1213      *
1214      * @param int $userid The id of the user who we are viewing conversations for
1215      * @param int $limitfrom
1216      * @param int $limitnum
1217      * @return stdClass
1218      * @throws moodle_exception
1219      * @since 3.2
1220      */
1221     public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
1222         global $CFG, $PAGE, $USER;
1224         // Check if messaging is enabled.
1225         if (empty($CFG->messaging)) {
1226             throw new moodle_exception('disabled', 'message');
1227         }
1229         $systemcontext = context_system::instance();
1231         $params = array(
1232             'userid' => $userid,
1233             'limitfrom' => $limitfrom,
1234             'limitnum' => $limitnum
1235         );
1236         self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
1237         self::validate_context($systemcontext);
1239         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1240             throw new moodle_exception('You do not have permission to perform this action.');
1241         }
1243         $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
1244         $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
1246         $renderer = $PAGE->get_renderer('core_message');
1247         return $contacts->export_for_template($renderer);
1248     }
1250     /**
1251      * The messagearea contacts return structure.
1252      *
1253      * @return external_single_structure
1254      * @since 3.2
1255      */
1256     public static function data_for_messagearea_contacts_returns() {
1257         return self::data_for_messagearea_conversations_returns();
1258     }
1260     /**
1261      * The messagearea messages parameters.
1262      *
1263      * @return external_function_parameters
1264      * @since 3.2
1265      */
1266     public static function data_for_messagearea_messages_parameters() {
1267         return new external_function_parameters(
1268             array(
1269                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1270                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1271                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
1272                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
1273                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
1274                 'timefrom' => new external_value(PARAM_INT,
1275                     'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
1276             )
1277         );
1278     }
1280     /**
1281      * Get messagearea messages.
1282      *
1283      * @param int $currentuserid The current user's id
1284      * @param int $otheruserid The other user's id
1285      * @param int $limitfrom
1286      * @param int $limitnum
1287      * @param boolean $newest
1288      * @return stdClass
1289      * @throws moodle_exception
1290      * @since 3.2
1291      */
1292     public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
1293                                                          $newest = false, $timefrom = 0) {
1294         global $CFG, $PAGE, $USER;
1296         // Check if messaging is enabled.
1297         if (empty($CFG->messaging)) {
1298             throw new moodle_exception('disabled', 'message');
1299         }
1301         $systemcontext = context_system::instance();
1303         $params = array(
1304             'currentuserid' => $currentuserid,
1305             'otheruserid' => $otheruserid,
1306             'limitfrom' => $limitfrom,
1307             'limitnum' => $limitnum,
1308             'newest' => $newest,
1309             'timefrom' => $timefrom,
1310         );
1311         self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
1312         self::validate_context($systemcontext);
1314         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1315             throw new moodle_exception('You do not have permission to perform this action.');
1316         }
1318         if ($newest) {
1319             $sort = 'timecreated DESC';
1320         } else {
1321             $sort = 'timecreated ASC';
1322         }
1324         // We need to enforce a one second delay on messages to avoid race conditions of current
1325         // messages still being sent.
1326         //
1327         // There is a chance that we could request messages before the current time's
1328         // second has elapsed and while other messages are being sent in that same second. In which
1329         // case those messages will be lost.
1330         //
1331         // Instead we ignore the current time in the result set to ensure that second is allowed to finish.
1332         if (!empty($timefrom)) {
1333             $timeto = time() - 1;
1334         } else {
1335             $timeto = 0;
1336         }
1338         // No requesting messages from the current time, as stated above.
1339         if ($timefrom == time()) {
1340             $messages = [];
1341         } else {
1342             $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
1343                                                         $limitnum, $sort, $timefrom, $timeto);
1344         }
1346         $messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
1348         $renderer = $PAGE->get_renderer('core_message');
1349         return $messages->export_for_template($renderer);
1350     }
1352     /**
1353      * The messagearea messages return structure.
1354      *
1355      * @return external_single_structure
1356      * @since 3.2
1357      */
1358     public static function data_for_messagearea_messages_returns() {
1359         return new external_single_structure(
1360             array(
1361                 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
1362                     the messages on behalf of?'),
1363                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1364                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1365                 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
1366                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1367                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1368                 'messages' => new external_multiple_structure(
1369                     self::get_messagearea_message_structure()
1370                 ),
1371                 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
1372             )
1373         );
1374     }
1376     /**
1377      * The get most recent message return parameters.
1378      *
1379      * @return external_function_parameters
1380      * @since 3.2
1381      */
1382     public static function data_for_messagearea_get_most_recent_message_parameters() {
1383         return new external_function_parameters(
1384             array(
1385                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1386                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
1387             )
1388         );
1389     }
1391     /**
1392      * Get the most recent message in a conversation.
1393      *
1394      * @param int $currentuserid The current user's id
1395      * @param int $otheruserid The other user's id
1396      * @return stdClass
1397      * @throws moodle_exception
1398      * @since 3.2
1399      */
1400     public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
1401         global $CFG, $PAGE, $USER;
1403         // Check if messaging is enabled.
1404         if (empty($CFG->messaging)) {
1405             throw new moodle_exception('disabled', 'message');
1406         }
1408         $systemcontext = context_system::instance();
1410         $params = array(
1411             'currentuserid' => $currentuserid,
1412             'otheruserid' => $otheruserid
1413         );
1414         self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
1415         self::validate_context($systemcontext);
1417         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1418             throw new moodle_exception('You do not have permission to perform this action.');
1419         }
1421         $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
1422         $message = new \core_message\output\messagearea\message($message);
1424         $renderer = $PAGE->get_renderer('core_message');
1425         return $message->export_for_template($renderer);
1426     }
1428     /**
1429      * The get most recent message return structure.
1430      *
1431      * @return external_single_structure
1432      * @since 3.2
1433      */
1434     public static function data_for_messagearea_get_most_recent_message_returns() {
1435         return self::get_messagearea_message_structure();
1436     }
1438     /**
1439      * The get profile parameters.
1440      *
1441      * @return external_function_parameters
1442      * @since 3.2
1443      */
1444     public static function data_for_messagearea_get_profile_parameters() {
1445         return new external_function_parameters(
1446             array(
1447                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1448                 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
1449             )
1450         );
1451     }
1453     /**
1454      * Get the profile information for a contact.
1455      *
1456      * @param int $currentuserid The current user's id
1457      * @param int $otheruserid The id of the user whose profile we are viewing
1458      * @return stdClass
1459      * @throws moodle_exception
1460      * @since 3.2
1461      */
1462     public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
1463         global $CFG, $PAGE, $USER;
1465         // Check if messaging is enabled.
1466         if (empty($CFG->messaging)) {
1467             throw new moodle_exception('disabled', 'message');
1468         }
1470         $systemcontext = context_system::instance();
1472         $params = array(
1473             'currentuserid' => $currentuserid,
1474             'otheruserid' => $otheruserid
1475         );
1476         self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
1477         self::validate_context($systemcontext);
1479         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1480             throw new moodle_exception('You do not have permission to perform this action.');
1481         }
1483         $profile = \core_message\api::get_profile($currentuserid, $otheruserid);
1484         $profile = new \core_message\output\messagearea\profile($profile);
1486         $renderer = $PAGE->get_renderer('core_message');
1487         return $profile->export_for_template($renderer);
1488     }
1490     /**
1491      * The get profile return structure.
1492      *
1493      * @return external_single_structure
1494      * @since 3.2
1495      */
1496     public static function data_for_messagearea_get_profile_returns() {
1497         return new external_single_structure(
1498             array(
1499                 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
1500                 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
1501                 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
1502                 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
1503                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1504                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1505                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1506                 'showonlinestatus' => new external_value(PARAM_BOOL, 'Show the user\'s online status?'),
1507                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1508                 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
1509                 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
1510             )
1511         );
1512     }
1514     /**
1515      * Get contacts parameters description.
1516      *
1517      * @return external_function_parameters
1518      * @since Moodle 2.5
1519      */
1520     public static function get_contacts_parameters() {
1521         return new external_function_parameters(array());
1522     }
1524     /**
1525      * Get contacts.
1526      *
1527      * @return external_description
1528      * @since Moodle 2.5
1529      */
1530     public static function get_contacts() {
1531         global $CFG, $PAGE, $USER;
1533         // Check if messaging is enabled.
1534         if (empty($CFG->messaging)) {
1535             throw new moodle_exception('disabled', 'message');
1536         }
1538         require_once($CFG->dirroot . '/user/lib.php');
1540         $allcontacts = array('online' => [], 'offline' => [], 'strangers' => []);
1541         $contacts = \core_message\api::get_contacts_with_unread_message_count($USER->id);
1542         foreach ($contacts as $contact) {
1543             // Set the mode.
1544             $mode = 'offline';
1545             if (\core_message\helper::is_online($contact->lastaccess)) {
1546                 $mode = 'online';
1547             }
1549             $newcontact = array(
1550                 'id' => $contact->id,
1551                 'fullname' => fullname($contact),
1552                 'unread' => $contact->messagecount
1553             );
1555             $userpicture = new user_picture($contact);
1556             $userpicture->size = 1; // Size f1.
1557             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1558             $userpicture->size = 0; // Size f2.
1559             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1561             $allcontacts[$mode][$contact->id] = $newcontact;
1562         }
1564         $strangers = \core_message\api::get_non_contacts_with_unread_message_count($USER->id);
1565         foreach ($strangers as $contact) {
1566             $newcontact = array(
1567                 'id' => $contact->id,
1568                 'fullname' => fullname($contact),
1569                 'unread' => $contact->messagecount
1570             );
1572             $userpicture = new user_picture($contact);
1573             $userpicture->size = 1; // Size f1.
1574             $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1575             $userpicture->size = 0; // Size f2.
1576             $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1578             $allcontacts['strangers'][$contact->id] = $newcontact;
1579         }
1581         // Add noreply user and support user to the list, if they don't exist.
1582         $supportuser = core_user::get_support_user();
1583         if (!isset($strangers[$supportuser->id]) && !$supportuser->deleted) {
1584             $supportuser->messagecount = message_count_unread_messages($USER, $supportuser);
1585             if ($supportuser->messagecount > 0) {
1586                 $supportuser->fullname = fullname($supportuser);
1587                 $supportuser->unread = $supportuser->messagecount;
1588                 $allcontacts['strangers'][$supportuser->id] = $supportuser;
1589             }
1590         }
1592         $noreplyuser = core_user::get_noreply_user();
1593         if (!isset($strangers[$noreplyuser->id]) && !$noreplyuser->deleted) {
1594             $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser);
1595             if ($noreplyuser->messagecount > 0) {
1596                 $noreplyuser->fullname = fullname($noreplyuser);
1597                 $noreplyuser->unread = $noreplyuser->messagecount;
1598                 $allcontacts['strangers'][$noreplyuser->id] = $noreplyuser;
1599             }
1600         }
1602         return $allcontacts;
1603     }
1605     /**
1606      * Get contacts return description.
1607      *
1608      * @return external_description
1609      * @since Moodle 2.5
1610      */
1611     public static function get_contacts_returns() {
1612         return new external_single_structure(
1613             array(
1614                 'online' => new external_multiple_structure(
1615                     new external_single_structure(
1616                         array(
1617                             'id' => new external_value(PARAM_INT, 'User ID'),
1618                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1619                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1620                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1621                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1622                         )
1623                     ),
1624                     'List of online contacts'
1625                 ),
1626                 'offline' => new external_multiple_structure(
1627                     new external_single_structure(
1628                         array(
1629                             'id' => new external_value(PARAM_INT, 'User ID'),
1630                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1631                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1632                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1633                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1634                         )
1635                     ),
1636                     'List of offline contacts'
1637                 ),
1638                 'strangers' => new external_multiple_structure(
1639                     new external_single_structure(
1640                         array(
1641                             'id' => new external_value(PARAM_INT, 'User ID'),
1642                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1643                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1644                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1645                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1646                         )
1647                     ),
1648                     'List of users that are not in the user\'s contact list but have sent a message'
1649                 )
1650             )
1651         );
1652     }
1654     /**
1655      * Search contacts parameters description.
1656      *
1657      * @return external_function_parameters
1658      * @since Moodle 2.5
1659      */
1660     public static function search_contacts_parameters() {
1661         return new external_function_parameters(
1662             array(
1663                 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
1664                 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
1665                     VALUE_DEFAULT, false)
1666             )
1667         );
1668     }
1670     /**
1671      * Search contacts.
1672      *
1673      * @param string $searchtext query string.
1674      * @param bool $onlymycourses limit the search to the user's courses only.
1675      * @return external_description
1676      * @since Moodle 2.5
1677      */
1678     public static function search_contacts($searchtext, $onlymycourses = false) {
1679         global $CFG, $USER, $PAGE;
1680         require_once($CFG->dirroot . '/user/lib.php');
1682         // Check if messaging is enabled.
1683         if (empty($CFG->messaging)) {
1684             throw new moodle_exception('disabled', 'message');
1685         }
1687         require_once($CFG->libdir . '/enrollib.php');
1689         $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
1690         $params = self::validate_parameters(self::search_contacts_parameters(), $params);
1692         // Extra validation, we do not allow empty queries.
1693         if ($params['searchtext'] === '') {
1694             throw new moodle_exception('querystringcannotbeempty');
1695         }
1697         $courseids = array();
1698         if ($params['onlymycourses']) {
1699             $mycourses = enrol_get_my_courses(array('id'));
1700             foreach ($mycourses as $mycourse) {
1701                 $courseids[] = $mycourse->id;
1702             }
1703         } else {
1704             $courseids[] = SITEID;
1705         }
1707         // Retrieving the users matching the query.
1708         $users = message_search_users($courseids, $params['searchtext']);
1709         $results = array();
1710         foreach ($users as $user) {
1711             $results[$user->id] = $user;
1712         }
1714         // Reorganising information.
1715         foreach ($results as &$user) {
1716             $newuser = array(
1717                 'id' => $user->id,
1718                 'fullname' => fullname($user)
1719             );
1721             // Avoid undefined property notice as phone not specified.
1722             $user->phone1 = null;
1723             $user->phone2 = null;
1725             $userpicture = new user_picture($user);
1726             $userpicture->size = 1; // Size f1.
1727             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1728             $userpicture->size = 0; // Size f2.
1729             $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1731             $user = $newuser;
1732         }
1734         return $results;
1735     }
1737     /**
1738      * Search contacts return description.
1739      *
1740      * @return external_description
1741      * @since Moodle 2.5
1742      */
1743     public static function search_contacts_returns() {
1744         return new external_multiple_structure(
1745             new external_single_structure(
1746                 array(
1747                     'id' => new external_value(PARAM_INT, 'User ID'),
1748                     'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1749                     'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1750                     'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
1751                 )
1752             ),
1753             'List of contacts'
1754         );
1755     }
1757     /**
1758      * Get messages parameters description.
1759      *
1760      * @return external_function_parameters
1761      * @since 2.8
1762      */
1763     public static function get_messages_parameters() {
1764         return new external_function_parameters(
1765             array(
1766                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1767                 'useridfrom' => new external_value(
1768                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1769                     VALUE_DEFAULT, 0),
1770                 'type' => new external_value(
1771                     PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
1772                     VALUE_DEFAULT, 'both'),
1773                 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
1774                 'newestfirst' => new external_value(
1775                     PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
1776                     VALUE_DEFAULT, true),
1777                 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
1778                 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
1779             )
1780         );
1781     }
1783     /**
1784      * Get messages function implementation.
1785      *
1786      * @since  2.8
1787      * @throws invalid_parameter_exception
1788      * @throws moodle_exception
1789      * @param  int      $useridto       the user id who received the message
1790      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
1791      * @param  string   $type           type of message to return, expected values: notifications, conversations and both
1792      * @param  bool     $read           true for retreiving read messages, false for unread
1793      * @param  bool     $newestfirst    true for ordering by newest first, false for oldest first
1794      * @param  int      $limitfrom      limit from
1795      * @param  int      $limitnum       limit num
1796      * @return external_description
1797      */
1798     public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
1799                                         $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
1800         global $CFG, $USER;
1802         $warnings = array();
1804         $params = array(
1805             'useridto' => $useridto,
1806             'useridfrom' => $useridfrom,
1807             'type' => $type,
1808             'read' => $read,
1809             'newestfirst' => $newestfirst,
1810             'limitfrom' => $limitfrom,
1811             'limitnum' => $limitnum
1812         );
1814         $params = self::validate_parameters(self::get_messages_parameters(), $params);
1816         $context = context_system::instance();
1817         self::validate_context($context);
1819         $useridto = $params['useridto'];
1820         $useridfrom = $params['useridfrom'];
1821         $type = $params['type'];
1822         $read = $params['read'];
1823         $newestfirst = $params['newestfirst'];
1824         $limitfrom = $params['limitfrom'];
1825         $limitnum = $params['limitnum'];
1827         $allowedvalues = array('notifications', 'conversations', 'both');
1828         if (!in_array($type, $allowedvalues)) {
1829             throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
1830                 'allowed values are: ' . implode(',', $allowedvalues));
1831         }
1833         // Check if private messaging between users is allowed.
1834         if (empty($CFG->messaging)) {
1835             // If we are retreiving only conversations, and messaging is disabled, throw an exception.
1836             if ($type == "conversations") {
1837                 throw new moodle_exception('disabled', 'message');
1838             }
1839             if ($type == "both") {
1840                 $warning = array();
1841                 $warning['item'] = 'message';
1842                 $warning['itemid'] = $USER->id;
1843                 $warning['warningcode'] = '1';
1844                 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
1845                     Only notifications will be returned';
1846                 $warnings[] = $warning;
1847             }
1848         }
1850         if (!empty($useridto)) {
1851             if (core_user::is_real_user($useridto)) {
1852                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1853             } else {
1854                 throw new moodle_exception('invaliduser');
1855             }
1856         }
1858         if (!empty($useridfrom)) {
1859             // We use get_user here because the from user can be the noreply or support user.
1860             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1861         }
1863         // Check if the current user is the sender/receiver or just a privileged user.
1864         if ($useridto != $USER->id and $useridfrom != $USER->id and
1865              !has_capability('moodle/site:readallmessages', $context)) {
1866             throw new moodle_exception('accessdenied', 'admin');
1867         }
1869         // Which type of messages to retrieve.
1870         $notifications = -1;
1871         if ($type != 'both') {
1872             $notifications = ($type == 'notifications') ? 1 : 0;
1873         }
1875         $orderdirection = $newestfirst ? 'DESC' : 'ASC';
1876         $sort = "mr.timecreated $orderdirection";
1878         if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
1879             $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
1881             // In some cases, we don't need to get the to/from user objects from the sql query.
1882             $userfromfullname = '';
1883             $usertofullname = '';
1885             // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
1886             if (!empty($useridto)) {
1887                 $usertofullname = fullname($userto, $canviewfullname);
1888                 // The user from may or may not be filled.
1889                 if (!empty($useridfrom)) {
1890                     $userfromfullname = fullname($userfrom, $canviewfullname);
1891                 }
1892             } else {
1893                 // If the useridto field is empty, the useridfrom must be filled.
1894                 $userfromfullname = fullname($userfrom, $canviewfullname);
1895             }
1896             foreach ($messages as $mid => $message) {
1898                 // Do not return deleted messages.
1899                 if (!$message->notification) {
1900                     if (($useridto == $USER->id and $message->timeusertodeleted) or
1901                         ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
1902                         unset($messages[$mid]);
1903                         continue;
1904                     }
1905                 }
1907                 // We need to get the user from the query.
1908                 if (empty($userfromfullname)) {
1909                     // Check for non-reply and support users.
1910                     if (core_user::is_real_user($message->useridfrom)) {
1911                         $user = new stdClass();
1912                         $user = username_load_fields_from_object($user, $message, 'userfrom');
1913                         $message->userfromfullname = fullname($user, $canviewfullname);
1914                     } else {
1915                         $user = core_user::get_user($message->useridfrom);
1916                         $message->userfromfullname = fullname($user, $canviewfullname);
1917                     }
1918                 } else {
1919                     $message->userfromfullname = $userfromfullname;
1920                 }
1922                 // We need to get the user from the query.
1923                 if (empty($usertofullname)) {
1924                     $user = new stdClass();
1925                     $user = username_load_fields_from_object($user, $message, 'userto');
1926                     $message->usertofullname = fullname($user, $canviewfullname);
1927                 } else {
1928                     $message->usertofullname = $usertofullname;
1929                 }
1931                 $message->text = message_format_message_text($message);
1932                 $messages[$mid] = (array) $message;
1933             }
1934         }
1936         $results = array(
1937             'messages' => $messages,
1938             'warnings' => $warnings
1939         );
1941         return $results;
1942     }
1944     /**
1945      * Get messages return description.
1946      *
1947      * @return external_single_structure
1948      * @since 2.8
1949      */
1950     public static function get_messages_returns() {
1951         return new external_single_structure(
1952             array(
1953                 'messages' => new external_multiple_structure(
1954                     new external_single_structure(
1955                         array(
1956                             'id' => new external_value(PARAM_INT, 'Message id'),
1957                             'useridfrom' => new external_value(PARAM_INT, 'User from id'),
1958                             'useridto' => new external_value(PARAM_INT, 'User to id'),
1959                             'subject' => new external_value(PARAM_TEXT, 'The message subject'),
1960                             'text' => new external_value(PARAM_RAW, 'The message text formated'),
1961                             'fullmessage' => new external_value(PARAM_RAW, 'The message'),
1962                             'fullmessageformat' => new external_format_value('fullmessage'),
1963                             'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
1964                             'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
1965                             'notification' => new external_value(PARAM_INT, 'Is a notification?'),
1966                             'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
1967                             'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
1968                             'timecreated' => new external_value(PARAM_INT, 'Time created'),
1969                             'timeread' => new external_value(PARAM_INT, 'Time read'),
1970                             'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
1971                             'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
1972                         ), 'message'
1973                     )
1974                 ),
1975                 'warnings' => new external_warnings()
1976             )
1977         );
1978     }
1980     /**
1981      * Mark all notifications as read parameters description.
1982      *
1983      * @return external_function_parameters
1984      * @since 3.2
1985      */
1986     public static function mark_all_notifications_as_read_parameters() {
1987         return new external_function_parameters(
1988             array(
1989                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1990                 'useridfrom' => new external_value(
1991                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1992                     VALUE_DEFAULT, 0),
1993             )
1994         );
1995     }
1997     /**
1998      * Mark all notifications as read function.
1999      *
2000      * @since  3.2
2001      * @throws invalid_parameter_exception
2002      * @throws moodle_exception
2003      * @param  int      $useridto       the user id who received the message
2004      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
2005      * @return external_description
2006      */
2007     public static function mark_all_notifications_as_read($useridto, $useridfrom) {
2008         global $USER;
2010         $params = self::validate_parameters(
2011             self::mark_all_notifications_as_read_parameters(),
2012             array(
2013                 'useridto' => $useridto,
2014                 'useridfrom' => $useridfrom,
2015             )
2016         );
2018         $context = context_system::instance();
2019         self::validate_context($context);
2021         $useridto = $params['useridto'];
2022         $useridfrom = $params['useridfrom'];
2024         if (!empty($useridto)) {
2025             if (core_user::is_real_user($useridto)) {
2026                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2027             } else {
2028                 throw new moodle_exception('invaliduser');
2029             }
2030         }
2032         if (!empty($useridfrom)) {
2033             // We use get_user here because the from user can be the noreply or support user.
2034             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2035         }
2037         // Check if the current user is the sender/receiver or just a privileged user.
2038         if ($useridto != $USER->id and $useridfrom != $USER->id and
2039             // The deleteanymessage cap seems more reasonable here than readallmessages.
2040              !has_capability('moodle/site:deleteanymessage', $context)) {
2041             throw new moodle_exception('accessdenied', 'admin');
2042         }
2044         \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom);
2046         return true;
2047     }
2049     /**
2050      * Mark all notifications as read return description.
2051      *
2052      * @return external_single_structure
2053      * @since 3.2
2054      */
2055     public static function mark_all_notifications_as_read_returns() {
2056         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2057     }
2059     /**
2060      * Get unread conversations count parameters description.
2061      *
2062      * @return external_function_parameters
2063      * @since 3.2
2064      */
2065     public static function get_unread_conversations_count_parameters() {
2066         return new external_function_parameters(
2067             array(
2068                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2069             )
2070         );
2071     }
2073     /**
2074      * Get unread messages count function.
2075      *
2076      * @since  3.2
2077      * @throws invalid_parameter_exception
2078      * @throws moodle_exception
2079      * @param  int      $useridto       the user id who received the message
2080      * @return external_description
2081      */
2082     public static function get_unread_conversations_count($useridto) {
2083         global $USER, $CFG;
2085         // Check if messaging is enabled.
2086         if (empty($CFG->messaging)) {
2087             throw new moodle_exception('disabled', 'message');
2088         }
2090         $params = self::validate_parameters(
2091             self::get_unread_conversations_count_parameters(),
2092             array('useridto' => $useridto)
2093         );
2095         $context = context_system::instance();
2096         self::validate_context($context);
2098         $useridto = $params['useridto'];
2100         if (!empty($useridto)) {
2101             if (core_user::is_real_user($useridto)) {
2102                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2103             } else {
2104                 throw new moodle_exception('invaliduser');
2105             }
2106         } else {
2107             $useridto = $USER->id;
2108         }
2110         // Check if the current user is the receiver or just a privileged user.
2111         if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
2112             throw new moodle_exception('accessdenied', 'admin');
2113         }
2115         return \core_message\api::count_unread_conversations($userto);
2116     }
2118     /**
2119      * Get unread conversations count return description.
2120      *
2121      * @return external_single_structure
2122      * @since 3.2
2123      */
2124     public static function get_unread_conversations_count_returns() {
2125         return new external_value(PARAM_INT, 'The count of unread messages for the user');
2126     }
2128     /**
2129      * Get blocked users parameters description.
2130      *
2131      * @return external_function_parameters
2132      * @since 2.9
2133      */
2134     public static function get_blocked_users_parameters() {
2135         return new external_function_parameters(
2136             array(
2137                 'userid' => new external_value(PARAM_INT,
2138                                 'the user whose blocked users we want to retrieve',
2139                                 VALUE_REQUIRED),
2140             )
2141         );
2142     }
2144     /**
2145      * Retrieve a list of users blocked
2146      *
2147      * @param  int $userid the user whose blocked users we want to retrieve
2148      * @return external_description
2149      * @since 2.9
2150      */
2151     public static function get_blocked_users($userid) {
2152         global $CFG, $USER, $PAGE;
2154         // Warnings array, it can be empty at the end but is mandatory.
2155         $warnings = array();
2157         // Validate params.
2158         $params = array(
2159             'userid' => $userid
2160         );
2161         $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
2162         $userid = $params['userid'];
2164         // Validate context.
2165         $context = context_system::instance();
2166         self::validate_context($context);
2168         // Check if private messaging between users is allowed.
2169         if (empty($CFG->messaging)) {
2170             throw new moodle_exception('disabled', 'message');
2171         }
2173         $user = core_user::get_user($userid, '*', MUST_EXIST);
2174         core_user::require_active_user($user);
2176         // Check if we have permissions for retrieve the information.
2177         $capability = 'moodle/site:manageallmessaging';
2178         if (($USER->id != $userid) && !has_capability($capability, $context)) {
2179             throw new required_capability_exception($context, $capability, 'nopermissions', '');
2180         }
2182         // Now, we can get safely all the blocked users.
2183         $users = \core_message\api::get_blocked_users($user->id);
2185         $blockedusers = array();
2186         foreach ($users as $user) {
2187             $newuser = array(
2188                 'id' => $user->id,
2189                 'fullname' => fullname($user),
2190             );
2192             $userpicture = new user_picture($user);
2193             $userpicture->size = 1; // Size f1.
2194             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
2196             $blockedusers[] = $newuser;
2197         }
2199         $results = array(
2200             'users' => $blockedusers,
2201             'warnings' => $warnings
2202         );
2203         return $results;
2204     }
2206     /**
2207      * Get blocked users return description.
2208      *
2209      * @return external_single_structure
2210      * @since 2.9
2211      */
2212     public static function get_blocked_users_returns() {
2213         return new external_single_structure(
2214             array(
2215                 'users' => new external_multiple_structure(
2216                     new external_single_structure(
2217                         array(
2218                             'id' => new external_value(PARAM_INT, 'User ID'),
2219                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
2220                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
2221                         )
2222                     ),
2223                     'List of blocked users'
2224                 ),
2225                 'warnings' => new external_warnings()
2226             )
2227         );
2228     }
2230     /**
2231      * Returns description of method parameters
2232      *
2233      * @return external_function_parameters
2234      * @since 2.9
2235      */
2236     public static function mark_message_read_parameters() {
2237         return new external_function_parameters(
2238             array(
2239                 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'),
2240                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
2241                     VALUE_DEFAULT, 0)
2242             )
2243         );
2244     }
2246     /**
2247      * Mark a single message as read, trigger message_viewed event
2248      *
2249      * @param  int $messageid id of the message (in the message table)
2250      * @param  int $timeread timestamp for when the message should be marked read
2251      * @return external_description
2252      * @throws invalid_parameter_exception
2253      * @throws moodle_exception
2254      * @since 2.9
2255      */
2256     public static function mark_message_read($messageid, $timeread) {
2257         global $CFG, $DB, $USER;
2259         // Check if private messaging between users is allowed.
2260         if (empty($CFG->messaging)) {
2261             throw new moodle_exception('disabled', 'message');
2262         }
2264         // Warnings array, it can be empty at the end but is mandatory.
2265         $warnings = array();
2267         // Validate params.
2268         $params = array(
2269             'messageid' => $messageid,
2270             'timeread' => $timeread
2271         );
2272         $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
2274         if (empty($params['timeread'])) {
2275             $timeread = time();
2276         } else {
2277             $timeread = $params['timeread'];
2278         }
2280         // Validate context.
2281         $context = context_system::instance();
2282         self::validate_context($context);
2284         $sql = "SELECT m.*, mcm.userid as useridto
2285                   FROM {messages} m
2286             INNER JOIN {message_conversations} mc
2287                     ON m.conversationid = mc.id
2288             INNER JOIN {message_conversation_members} mcm
2289                     ON mcm.conversationid = mc.id
2290              LEFT JOIN {message_user_actions} mua
2291                     ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?)
2292                  WHERE mua.id is NULL
2293                    AND mcm.userid != m.useridfrom
2294                    AND m.id = ?";
2295         $messageparams = [];
2296         $messageparams[] = $USER->id;
2297         $messageparams[] = \core_message\api::MESSAGE_ACTION_READ;
2298         $messageparams[] = $params['messageid'];
2299         $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST);
2301         if ($message->useridto != $USER->id) {
2302             throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
2303         }
2305         \core_message\api::mark_message_as_read($USER->id, $message, $timeread);
2307         $results = array(
2308             'messageid' => $message->id,
2309             'warnings' => $warnings
2310         );
2311         return $results;
2312     }
2314     /**
2315      * Returns description of method result value
2316      *
2317      * @return external_description
2318      * @since 2.9
2319      */
2320     public static function mark_message_read_returns() {
2321         return new external_single_structure(
2322             array(
2323                 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'),
2324                 'warnings' => new external_warnings()
2325             )
2326         );
2327     }
2329     /**
2330      * Returns description of method parameters
2331      *
2332      * @return external_function_parameters
2333      */
2334     public static function mark_notification_read_parameters() {
2335         return new external_function_parameters(
2336             array(
2337                 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2338                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read',
2339                     VALUE_DEFAULT, 0)
2340             )
2341         );
2342     }
2344     /**
2345      * Mark a single notification as read.
2346      *
2347      * This will trigger a 'notification_viewed' event.
2348      *
2349      * @param int $notificationid id of the notification
2350      * @param int $timeread timestamp for when the notification should be marked read
2351      * @return external_description
2352      * @throws invalid_parameter_exception
2353      * @throws moodle_exception
2354      */
2355     public static function mark_notification_read($notificationid, $timeread) {
2356         global $CFG, $DB, $USER;
2358         // Check if private messaging between users is allowed.
2359         if (empty($CFG->messaging)) {
2360             throw new moodle_exception('disabled', 'message');
2361         }
2363         // Warnings array, it can be empty at the end but is mandatory.
2364         $warnings = array();
2366         // Validate params.
2367         $params = array(
2368             'notificationid' => $notificationid,
2369             'timeread' => $timeread
2370         );
2371         $params = self::validate_parameters(self::mark_notification_read_parameters(), $params);
2373         if (empty($params['timeread'])) {
2374             $timeread = time();
2375         } else {
2376             $timeread = $params['timeread'];
2377         }
2379         // Validate context.
2380         $context = context_system::instance();
2381         self::validate_context($context);
2383         $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST);
2385         if ($notification->useridto != $USER->id) {
2386             throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' .
2387                 'notification as read');
2388         }
2390         \core_message\api::mark_notification_as_read($notification, $timeread);
2392         $results = array(
2393             'notificationid' => $notification->id,
2394             'warnings' => $warnings
2395         );
2397         return $results;
2398     }
2400     /**
2401      * Returns description of method result value
2402      *
2403      * @return external_description
2404      */
2405     public static function mark_notification_read_returns() {
2406         return new external_single_structure(
2407             array(
2408                 'notificationid' => new external_value(PARAM_INT, 'id of the notification'),
2409                 'warnings' => new external_warnings()
2410             )
2411         );
2412     }
2414     /**
2415      * Mark all messages as read parameters description.
2416      *
2417      * @return external_function_parameters
2418      * @since 3.2
2419      */
2420     public static function mark_all_messages_as_read_parameters() {
2421         return new external_function_parameters(
2422             array(
2423                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
2424                 'useridfrom' => new external_value(
2425                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
2426                     VALUE_DEFAULT, 0),
2427             )
2428         );
2429     }
2431     /**
2432      * Mark all notifications as read function.
2433      *
2434      * @since  3.2
2435      * @throws invalid_parameter_exception
2436      * @throws moodle_exception
2437      * @param  int      $useridto       the user id who received the message
2438      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
2439      * @return external_description
2440      */
2441     public static function mark_all_messages_as_read($useridto, $useridfrom) {
2442         global $USER, $CFG;
2444         // Check if messaging is enabled.
2445         if (empty($CFG->messaging)) {
2446             throw new moodle_exception('disabled', 'message');
2447         }
2449         $params = self::validate_parameters(
2450             self::mark_all_messages_as_read_parameters(),
2451             array(
2452                 'useridto' => $useridto,
2453                 'useridfrom' => $useridfrom,
2454             )
2455         );
2457         $context = context_system::instance();
2458         self::validate_context($context);
2460         $useridto = $params['useridto'];
2461         $useridfrom = $params['useridfrom'];
2463         if (!empty($useridto)) {
2464             if (core_user::is_real_user($useridto)) {
2465                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
2466             } else {
2467                 throw new moodle_exception('invaliduser');
2468             }
2469         }
2471         if (!empty($useridfrom)) {
2472             // We use get_user here because the from user can be the noreply or support user.
2473             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
2474         }
2476         // Check if the current user is the sender/receiver or just a privileged user.
2477         if ($useridto != $USER->id and $useridfrom != $USER->id and
2478             // The deleteanymessage cap seems more reasonable here than readallmessages.
2479              !has_capability('moodle/site:deleteanymessage', $context)) {
2480             throw new moodle_exception('accessdenied', 'admin');
2481         }
2483         if ($useridfrom) {
2484             if ($conversationid = \core_message\api::get_conversation_between_users([$useridto, $useridfrom])) {
2485                 \core_message\api::mark_all_messages_as_read($useridto, $conversationid);
2486             }
2487         } else {
2488             \core_message\api::mark_all_messages_as_read($useridto);
2489         }
2491         return true;
2492     }
2494     /**
2495      * Mark all notifications as read return description.
2496      *
2497      * @return external_single_structure
2498      * @since 3.2
2499      */
2500     public static function mark_all_messages_as_read_returns() {
2501         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
2502     }
2504     /**
2505      * Returns description of method parameters.
2506      *
2507      * @return external_function_parameters
2508      * @since 3.2
2509      */
2510     public static function delete_conversation_parameters() {
2511         return new external_function_parameters(
2512             array(
2513                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
2514                 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
2515             )
2516         );
2517     }
2519     /**
2520      * Deletes a conversation.
2521      *
2522      * @param int $userid The user id of who we want to delete the conversation for
2523      * @param int $otheruserid The user id of the other user in the conversation
2524      * @return array
2525      * @throws moodle_exception
2526      * @since 3.2
2527      */
2528     public static function delete_conversation($userid, $otheruserid) {
2529         global $CFG;
2531         // Check if private messaging between users is allowed.
2532         if (empty($CFG->messaging)) {
2533             throw new moodle_exception('disabled', 'message');
2534         }
2536         // Warnings array, it can be empty at the end but is mandatory.
2537         $warnings = array();
2539         // Validate params.
2540         $params = array(
2541             'userid' => $userid,
2542             'otheruserid' => $otheruserid,
2543         );
2544         $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
2546         // Validate context.
2547         $context = context_system::instance();
2548         self::validate_context($context);
2550         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2551         core_user::require_active_user($user);
2553         if (\core_message\api::can_delete_conversation($user->id)) {
2554             $status = \core_message\api::delete_conversation($user->id, $otheruserid);
2555         } else {
2556             throw new moodle_exception('You do not have permission to delete messages');
2557         }
2559         $results = array(
2560             'status' => $status,
2561             'warnings' => $warnings
2562         );
2564         return $results;
2565     }
2567     /**
2568      * Returns description of method result value.
2569      *
2570      * @return external_description
2571      * @since 3.2
2572      */
2573     public static function delete_conversation_returns() {
2574         return new external_single_structure(
2575             array(
2576                 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
2577                 'warnings' => new external_warnings()
2578             )
2579         );
2580     }
2582     /**
2583      * Returns description of method parameters
2584      *
2585      * @return external_function_parameters
2586      * @since 3.1
2587      */
2588     public static function delete_message_parameters() {
2589         return new external_function_parameters(
2590             array(
2591                 'messageid' => new external_value(PARAM_INT, 'The message id'),
2592                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
2593                 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
2594             )
2595         );
2596     }
2598     /**
2599      * Deletes a message
2600      *
2601      * @param  int $messageid the message id
2602      * @param  int $userid the user id of who we want to delete the message for
2603      * @param  bool $read if is a message read (default to true)
2604      * @return external_description
2605      * @throws moodle_exception
2606      * @since 3.1
2607      */
2608     public static function delete_message($messageid, $userid, $read = true) {
2609         global $CFG;
2611         // Check if private messaging between users is allowed.
2612         if (empty($CFG->messaging)) {
2613             throw new moodle_exception('disabled', 'message');
2614         }
2616         // Warnings array, it can be empty at the end but is mandatory.
2617         $warnings = array();
2619         // Validate params.
2620         $params = array(
2621             'messageid' => $messageid,
2622             'userid' => $userid,
2623             'read' => $read
2624         );
2625         $params = self::validate_parameters(self::delete_message_parameters(), $params);
2627         // Validate context.
2628         $context = context_system::instance();
2629         self::validate_context($context);
2631         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2632         core_user::require_active_user($user);
2634         if (\core_message\api::can_delete_message($user->id, $messageid)) {
2635             $status = \core_message\api::delete_message($user->id, $messageid);
2636         } else {
2637             throw new moodle_exception('You do not have permission to delete this message');
2638         }
2640         $results = array(
2641             'status' => $status,
2642             'warnings' => $warnings
2643         );
2644         return $results;
2645     }
2647     /**
2648      * Returns description of method result value
2649      *
2650      * @return external_description
2651      * @since 3.1
2652      */
2653     public static function delete_message_returns() {
2654         return new external_single_structure(
2655             array(
2656                 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
2657                 'warnings' => new external_warnings()
2658             )
2659         );
2660     }
2662     /**
2663      * Returns description of method parameters
2664      *
2665      * @return external_function_parameters
2666      * @since 3.2
2667      */
2668     public static function message_processor_config_form_parameters() {
2669         return new external_function_parameters(
2670             array(
2671                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
2672                 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
2673                 'formvalues' => new external_multiple_structure(
2674                     new external_single_structure(
2675                         array(
2676                             'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
2677                             'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
2678                         )
2679                     ),
2680                     'Config form values',
2681                     VALUE_REQUIRED
2682                 ),
2683             )
2684         );
2685     }
2687     /**
2688      * Processes a message processor config form.
2689      *
2690      * @param  int $userid the user id
2691      * @param  string $name the name of the processor
2692      * @param  array $formvalues the form values
2693      * @return external_description
2694      * @throws moodle_exception
2695      * @since 3.2
2696      */
2697     public static function message_processor_config_form($userid, $name, $formvalues) {
2698         global $USER, $CFG;
2700         // Check if messaging is enabled.
2701         if (empty($CFG->messaging)) {
2702             throw new moodle_exception('disabled', 'message');
2703         }
2705         $params = self::validate_parameters(
2706             self::message_processor_config_form_parameters(),
2707             array(
2708                 'userid' => $userid,
2709                 'name' => $name,
2710                 'formvalues' => $formvalues,
2711             )
2712         );
2714         $user = self::validate_preferences_permissions($params['userid']);
2716         $processor = get_message_processor($name);
2717         $preferences = [];
2718         $form = new stdClass();
2720         foreach ($formvalues as $formvalue) {
2721             // Curly braces to ensure interpretation is consistent between
2722             // php 5 and php 7.
2723             $form->{$formvalue['name']} = $formvalue['value'];
2724         }
2726         $processor->process_form($form, $preferences);
2728         if (!empty($preferences)) {
2729             set_user_preferences($preferences, $userid);
2730         }
2731     }
2733     /**
2734      * Returns description of method result value
2735      *
2736      * @return external_description
2737      * @since 3.2
2738      */
2739     public static function message_processor_config_form_returns() {
2740         return null;
2741     }
2743     /**
2744      * Returns description of method parameters
2745      *
2746      * @return external_function_parameters
2747      * @since 3.2
2748      */
2749     public static function get_message_processor_parameters() {
2750         return new external_function_parameters(
2751             array(
2752                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
2753                 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
2754             )
2755         );
2756     }
2758     /**
2759      * Get a message processor.
2760      *
2761      * @param int $userid
2762      * @param string $name the name of the processor
2763      * @return external_description
2764      * @throws moodle_exception
2765      * @since 3.2
2766      */
2767     public static function get_message_processor($userid = 0, $name) {
2768         global $USER, $PAGE, $CFG;
2770         // Check if messaging is enabled.
2771         if (empty($CFG->messaging)) {
2772             throw new moodle_exception('disabled', 'message');
2773         }
2775         $params = self::validate_parameters(
2776             self::get_message_processor_parameters(),
2777             array(
2778                 'userid' => $userid,
2779                 'name' => $name,
2780             )
2781         );
2783         if (empty($params['userid'])) {
2784             $params['userid'] = $USER->id;
2785         }
2787         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2788         core_user::require_active_user($user);
2789         self::validate_context(context_user::instance($params['userid']));
2791         $processor = get_message_processor($name);
2793         $processoroutput = new \core_message\output\processor($processor, $user);
2794         $renderer = $PAGE->get_renderer('core_message');
2796         return $processoroutput->export_for_template($renderer);
2797     }
2799     /**
2800      * Returns description of method result value
2801      *
2802      * @return external_description
2803      * @since 3.2
2804      */
2805     public static function get_message_processor_returns() {
2806         return new external_function_parameters(
2807             array(
2808                 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
2809                 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
2810             )
2811         );
2812     }
2814     /**
2815      * Check that the user has enough permission to retrieve message or notifications preferences.
2816      *
2817      * @param  int $userid the user id requesting the preferences
2818      * @return stdClass full user object
2819      * @throws moodle_exception
2820      * @since  Moodle 3.2
2821      */
2822     protected static function validate_preferences_permissions($userid) {
2823         global $USER;
2825         if (empty($userid)) {
2826             $user = $USER;
2827         } else {
2828             $user = core_user::get_user($userid, '*', MUST_EXIST);
2829             core_user::require_active_user($user);
2830         }
2832         $systemcontext = context_system::instance();
2833         self::validate_context($systemcontext);
2835         // Check access control.
2836         if ($user->id == $USER->id) {
2837             // Editing own message profile.
2838             require_capability('moodle/user:editownmessageprofile', $systemcontext);
2839         } else {
2840             // Teachers, parents, etc.
2841             $personalcontext = context_user::instance($user->id);
2842             require_capability('moodle/user:editmessageprofile', $personalcontext);
2843         }
2844         return $user;
2845     }
2847     /**
2848      * Returns a notification or message preference structure.
2849      *
2850      * @return external_single_structure the structure
2851      * @since  Moodle 3.2
2852      */
2853     protected static function get_preferences_structure() {
2854         return new external_single_structure(
2855             array(
2856                 'userid' => new external_value(PARAM_INT, 'User id'),
2857                 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
2858                 'processors' => new external_multiple_structure(
2859                     new external_single_structure(
2860                         array(
2861                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2862                             'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2863                             'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
2864                             'contextid' => new external_value(PARAM_INT, 'Context id'),
2865                             'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
2866                         )
2867                     ),
2868                     'Config form values'
2869                 ),
2870                 'components' => new external_multiple_structure(
2871                     new external_single_structure(
2872                         array(
2873                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2874                             'notifications' => new external_multiple_structure(
2875                                 new external_single_structure(
2876                                     array(
2877                                         'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2878                                         'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
2879                                         'processors' => new external_multiple_structure(
2880                                             new external_single_structure(
2881                                                 array(
2882                                                     'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2883                                                     'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2884                                                     'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
2885                                                     'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
2886                                                     'loggedin' => new external_single_structure(
2887                                                         array(
2888                                                             'name' => new external_value(PARAM_NOTAGS, 'Name'),
2889                                                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2890                                                             'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2891                                                         )
2892                                                     ),
2893                                                     'loggedoff' => new external_single_structure(
2894                                                         array(
2895                                                             'name' => new external_value(PARAM_NOTAGS, 'Name'),
2896                                                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2897                                                             'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2898                                                         )
2899                                                     ),
2900                                                 )
2901                                             ),
2902                                             'Processors values for this notification'
2903                                         ),
2904                                     )
2905                                 ),
2906                                 'List of notificaitons for the component'
2907                             ),
2908                         )
2909                     ),
2910                     'Available components'
2911                 ),
2912             )
2913         );
2914     }
2916     /**
2917      * Returns description of method parameters
2918      *
2919      * @return external_function_parameters
2920      * @since 3.2
2921      */
2922     public static function get_user_notification_preferences_parameters() {
2923         return new external_function_parameters(
2924             array(
2925                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
2926             )
2927         );
2928     }
2930     /**
2931      * Get the notification preferences for a given user.
2932      *
2933      * @param int $userid id of the user, 0 for current user
2934      * @return external_description
2935      * @throws moodle_exception
2936      * @since 3.2
2937      */
2938     public static function get_user_notification_preferences($userid = 0) {
2939         global $PAGE;
2941         $params = self::validate_parameters(
2942             self::get_user_notification_preferences_parameters(),
2943             array(
2944                 'userid' => $userid,
2945             )
2946         );
2947         $user = self::validate_preferences_permissions($params['userid']);
2949         $processors = get_message_processors();
2950         $providers = message_get_providers_for_user($user->id);
2951         $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2952         $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
2954         $renderer = $PAGE->get_renderer('core_message');
2956         $result = array(
2957             'warnings' => array(),
2958             'preferences' => $notificationlist->export_for_template($renderer)
2959         );
2960         return $result;
2961     }
2963     /**
2964      * Returns description of method result value
2965      *
2966      * @return external_description
2967      * @since 3.2
2968      */
2969     public static function get_user_notification_preferences_returns() {
2970         return new external_function_parameters(
2971             array(
2972                 'preferences' => self::get_preferences_structure(),
2973                 'warnings' => new external_warnings(),
2974             )
2975         );
2976     }
2979     /**
2980      * Returns description of method parameters
2981      *
2982      * @return external_function_parameters
2983      * @since 3.2
2984      */
2985     public static function get_user_message_preferences_parameters() {
2986         return new external_function_parameters(
2987             array(
2988                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
2989             )
2990         );
2991     }
2993     /**
2994      * Get the notification preferences for a given user.
2995      *
2996      * @param int $userid id of the user, 0 for current user
2997      * @return external_description
2998      * @throws moodle_exception
2999      * @since 3.2
3000      */
3001     public static function get_user_message_preferences($userid = 0) {
3002         global $PAGE;
3004         $params = self::validate_parameters(
3005             self::get_user_message_preferences_parameters(),
3006             array(
3007                 'userid' => $userid,
3008             )
3009         );
3011         $user = self::validate_preferences_permissions($params['userid']);
3013         // Filter out enabled, available system_configured and user_configured processors only.
3014         $readyprocessors = array_filter(get_message_processors(), function($processor) {
3015             return $processor->enabled &&
3016                 $processor->configured &&
3017                 $processor->object->is_user_configured() &&
3018                 // Filter out processors that don't have and message preferences to configure.
3019                 $processor->object->has_message_preferences();
3020         });
3022         $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
3023             return $provider->component === 'moodle';
3024         });
3025         $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
3026         $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
3027             $providers, $preferences, $user);
3029         $renderer = $PAGE->get_renderer('core_message');
3031         $result = array(
3032             'warnings' => array(),
3033             'preferences' => $notificationlistoutput->export_for_template($renderer),
3034             'blocknoncontacts' => \core_message\api::get_user_privacy_messaging_preference($user->id),
3035         );
3036         return $result;
3037     }
3039     /**
3040      * Returns description of method result value
3041      *
3042      * @return external_description
3043      * @since 3.2
3044      */
3045     public static function get_user_message_preferences_returns() {
3046         return new external_function_parameters(
3047             array(
3048                 'preferences' => self::get_preferences_structure(),
3049                 'blocknoncontacts' => new external_value(PARAM_INT, 'Privacy messaging setting to define who can message you'),
3050                 'warnings' => new external_warnings(),
3051             )
3052         );
3053     }