1d394bcac983e6e59c01df01064c3fcbfdaad0ce
[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 require_once("$CFG->libdir/externallib.php");
28 require_once($CFG->dirroot . "/message/lib.php");
30 /**
31  * Message external functions
32  *
33  * @package    core_message
34  * @category   external
35  * @copyright  2011 Jerome Mouneyrac
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  * @since Moodle 2.2
38  */
39 class core_message_external extends external_api {
41     /**
42      * Returns description of method parameters
43      *
44      * @return external_function_parameters
45      * @since Moodle 2.2
46      */
47     public static function send_instant_messages_parameters() {
48         return new external_function_parameters(
49             array(
50                 'messages' => new external_multiple_structure(
51                     new external_single_structure(
52                         array(
53                             'touserid' => new external_value(PARAM_INT, 'id of the user to send the private message'),
54                             'text' => new external_value(PARAM_RAW, 'the text of the message'),
55                             'textformat' => new external_format_value('text', VALUE_DEFAULT, FORMAT_MOODLE),
56                             '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),
57                         )
58                     )
59                 )
60             )
61         );
62     }
64     /**
65      * Send private messages from the current USER to other users
66      *
67      * @param array $messages An array of message to send.
68      * @return array
69      * @since Moodle 2.2
70      */
71     public static function send_instant_messages($messages = array()) {
72         global $CFG, $USER, $DB;
74         // Check if messaging is enabled.
75         if (empty($CFG->messaging)) {
76             throw new moodle_exception('disabled', 'message');
77         }
79         // Ensure the current user is allowed to run this function
80         $context = context_system::instance();
81         self::validate_context($context);
82         require_capability('moodle/site:sendmessage', $context);
84         $params = self::validate_parameters(self::send_instant_messages_parameters(), array('messages' => $messages));
86         //retrieve all tousers of the messages
87         $receivers = array();
88         foreach($params['messages'] as $message) {
89             $receivers[] = $message['touserid'];
90         }
91         list($sqluserids, $sqlparams) = $DB->get_in_or_equal($receivers, SQL_PARAMS_NAMED, 'userid_');
92         $tousers = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams);
93         $blocklist   = array();
94         $contactlist = array();
95         $sqlparams['contactid'] = $USER->id;
96         $rs = $DB->get_recordset_sql("SELECT *
97                                         FROM {message_contacts}
98                                        WHERE userid $sqluserids
99                                              AND contactid = :contactid", $sqlparams);
100         foreach ($rs as $record) {
101             if ($record->blocked) {
102                 // $record->userid is blocking current user
103                 $blocklist[$record->userid] = true;
104             } else {
105                 // $record->userid have current user as contact
106                 $contactlist[$record->userid] = true;
107             }
108         }
109         $rs->close();
111         $canreadallmessages = has_capability('moodle/site:readallmessages', $context);
113         $resultmessages = array();
114         foreach ($params['messages'] as $message) {
115             $resultmsg = array(); //the infos about the success of the operation
117             //we are going to do some checking
118             //code should match /messages/index.php checks
119             $success = true;
121             //check the user exists
122             if (empty($tousers[$message['touserid']])) {
123                 $success = false;
124                 $errormessage = get_string('touserdoesntexist', 'message', $message['touserid']);
125             }
127             //check that the touser is not blocking the current user
128             if ($success and !empty($blocklist[$message['touserid']]) and !$canreadallmessages) {
129                 $success = false;
130                 $errormessage = get_string('userisblockingyou', 'message');
131             }
133             // Check if the user is a contact
134             //TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
135             $blocknoncontacts = get_user_preferences('message_blocknoncontacts', NULL, $message['touserid']);
136             // message_blocknoncontacts option is on and current user is not in contact list
137             if ($success && empty($contactlist[$message['touserid']]) && !empty($blocknoncontacts)) {
138                 // The user isn't a contact and they have selected to block non contacts so this message won't be sent.
139                 $success = false;
140                 $errormessage = get_string('userisblockingyounoncontact', 'message',
141                         fullname(core_user::get_user($message['touserid'])));
142             }
144             //now we can send the message (at least try)
145             if ($success) {
146                 //TODO MDL-31118 performance improvement - edit the function so we can pass an array instead one touser object
147                 $success = message_post_message($USER, $tousers[$message['touserid']],
148                         $message['text'], external_validate_format($message['textformat']));
149             }
151             //build the resultmsg
152             if (isset($message['clientmsgid'])) {
153                 $resultmsg['clientmsgid'] = $message['clientmsgid'];
154             }
155             if ($success) {
156                 $resultmsg['msgid'] = $success;
157             } else {
158                 // WARNINGS: for backward compatibility we return this errormessage.
159                 //          We should have thrown exceptions as these errors prevent results to be returned.
160                 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side .
161                 $resultmsg['msgid'] = -1;
162                 $resultmsg['errormessage'] = $errormessage;
163             }
165             $resultmessages[] = $resultmsg;
166         }
168         return $resultmessages;
169     }
171     /**
172      * Returns description of method result value
173      *
174      * @return external_description
175      * @since Moodle 2.2
176      */
177     public static function send_instant_messages_returns() {
178         return new external_multiple_structure(
179             new external_single_structure(
180                 array(
181                     'msgid' => new external_value(PARAM_INT, 'test this to know if it succeeds:  id of the created message if it succeeded, -1 when failed'),
182                     'clientmsgid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the message', VALUE_OPTIONAL),
183                     'errormessage' => new external_value(PARAM_TEXT, 'error message - if it failed', VALUE_OPTIONAL)
184                 )
185             )
186         );
187     }
189     /**
190      * Create contacts parameters description.
191      *
192      * @return external_function_parameters
193      * @since Moodle 2.5
194      */
195     public static function create_contacts_parameters() {
196         return new external_function_parameters(
197             array(
198                 'userids' => new external_multiple_structure(
199                     new external_value(PARAM_INT, 'User ID'),
200                     'List of user IDs'
201                 ),
202                 'userid' => new external_value(PARAM_INT, 'The id of the user we are creating the contacts for, 0 for the
203                     current user', VALUE_DEFAULT, 0)
204             )
205         );
206     }
208     /**
209      * Create contacts.
210      *
211      * @param array $userids array of user IDs.
212      * @param int $userid The id of the user we are creating the contacts for
213      * @return external_description
214      * @since Moodle 2.5
215      */
216     public static function create_contacts($userids, $userid = 0) {
217         global $CFG, $USER;
219         // Check if messaging is enabled.
220         if (empty($CFG->messaging)) {
221             throw new moodle_exception('disabled', 'message');
222         }
224         if (empty($userid)) {
225             $userid = $USER->id;
226         }
228         // Validate context.
229         $context = context_system::instance();
230         self::validate_context($context);
232         $capability = 'moodle/site:manageallmessaging';
233         if (($USER->id != $userid) && !has_capability($capability, $context)) {
234             throw new required_capability_exception($context, $capability, 'nopermissions', '');
235         }
237         $params = array('userids' => $userids, 'userid' => $userid);
238         $params = self::validate_parameters(self::create_contacts_parameters(), $params);
240         $warnings = array();
241         foreach ($params['userids'] as $id) {
242             if (!message_add_contact($id, 0, $userid)) {
243                 $warnings[] = array(
244                     'item' => 'user',
245                     'itemid' => $id,
246                     'warningcode' => 'contactnotcreated',
247                     'message' => 'The contact could not be created'
248                 );
249             }
250         }
251         return $warnings;
252     }
254     /**
255      * Create contacts return description.
256      *
257      * @return external_description
258      * @since Moodle 2.5
259      */
260     public static function create_contacts_returns() {
261         return new external_warnings();
262     }
264     /**
265      * Delete contacts parameters description.
266      *
267      * @return external_function_parameters
268      * @since Moodle 2.5
269      */
270     public static function delete_contacts_parameters() {
271         return new external_function_parameters(
272             array(
273                 'userids' => new external_multiple_structure(
274                     new external_value(PARAM_INT, 'User ID'),
275                     'List of user IDs'
276                 ),
277                 'userid' => new external_value(PARAM_INT, 'The id of the user we are deleting the contacts for, 0 for the
278                     current user', VALUE_DEFAULT, 0)
279             )
280         );
281     }
283     /**
284      * Delete contacts.
285      *
286      * @param array $userids array of user IDs.
287      * @param int $userid The id of the user we are deleting the contacts for
288      * @return null
289      * @since Moodle 2.5
290      */
291     public static function delete_contacts($userids, $userid = 0) {
292         global $CFG, $USER;
294         // Check if messaging is enabled.
295         if (empty($CFG->messaging)) {
296             throw new moodle_exception('disabled', 'message');
297         }
299         if (empty($userid)) {
300             $userid = $USER->id;
301         }
303         // Validate context.
304         $context = context_system::instance();
305         self::validate_context($context);
307         $capability = 'moodle/site:manageallmessaging';
308         if (($USER->id != $userid) && !has_capability($capability, $context)) {
309             throw new required_capability_exception($context, $capability, 'nopermissions', '');
310         }
312         $params = array('userids' => $userids, 'userid' => $userid);
313         $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
315         foreach ($params['userids'] as $id) {
316             message_remove_contact($id, $userid);
317         }
319         return null;
320     }
322     /**
323      * Delete contacts return description.
324      *
325      * @return external_description
326      * @since Moodle 2.5
327      */
328     public static function delete_contacts_returns() {
329         return null;
330     }
332     /**
333      * Block contacts parameters description.
334      *
335      * @return external_function_parameters
336      * @since Moodle 2.5
337      */
338     public static function block_contacts_parameters() {
339         return new external_function_parameters(
340             array(
341                 'userids' => new external_multiple_structure(
342                     new external_value(PARAM_INT, 'User ID'),
343                     'List of user IDs'
344                 ),
345                 'userid' => new external_value(PARAM_INT, 'The id of the user we are blocking the contacts for, 0 for the
346                     current user', VALUE_DEFAULT, 0)
347             )
348         );
349     }
351     /**
352      * Block contacts.
353      *
354      * @param array $userids array of user IDs.
355      * @param int $userid The id of the user we are blocking the contacts for
356      * @return external_description
357      * @since Moodle 2.5
358      */
359     public static function block_contacts($userids, $userid = 0) {
360         global $CFG, $USER;
362         // Check if messaging is enabled.
363         if (empty($CFG->messaging)) {
364             throw new moodle_exception('disabled', 'message');
365         }
367         if (empty($userid)) {
368             $userid = $USER->id;
369         }
371         // Validate context.
372         $context = context_system::instance();
373         self::validate_context($context);
375         $capability = 'moodle/site:manageallmessaging';
376         if (($USER->id != $userid) && !has_capability($capability, $context)) {
377             throw new required_capability_exception($context, $capability, 'nopermissions', '');
378         }
380         $params = array('userids' => $userids, 'userid' => $userid);
381         $params = self::validate_parameters(self::block_contacts_parameters(), $params);
383         $warnings = array();
384         foreach ($params['userids'] as $id) {
385             if (!message_block_contact($id, $userid)) {
386                 $warnings[] = array(
387                     'item' => 'user',
388                     'itemid' => $id,
389                     'warningcode' => 'contactnotblocked',
390                     'message' => 'The contact could not be blocked'
391                 );
392             }
393         }
394         return $warnings;
395     }
397     /**
398      * Block contacts return description.
399      *
400      * @return external_description
401      * @since Moodle 2.5
402      */
403     public static function block_contacts_returns() {
404         return new external_warnings();
405     }
407     /**
408      * Unblock contacts parameters description.
409      *
410      * @return external_function_parameters
411      * @since Moodle 2.5
412      */
413     public static function unblock_contacts_parameters() {
414         return new external_function_parameters(
415             array(
416                 'userids' => new external_multiple_structure(
417                     new external_value(PARAM_INT, 'User ID'),
418                     'List of user IDs'
419                 ),
420                 'userid' => new external_value(PARAM_INT, 'The id of the user we are unblocking the contacts for, 0 for the
421                     current user', VALUE_DEFAULT, 0)
422             )
423         );
424     }
426     /**
427      * Unblock contacts.
428      *
429      * @param array $userids array of user IDs.
430      * @param int $userid The id of the user we are unblocking the contacts for
431      * @return null
432      * @since Moodle 2.5
433      */
434     public static function unblock_contacts($userids, $userid = 0) {
435         global $CFG, $USER;
437         // Check if messaging is enabled.
438         if (empty($CFG->messaging)) {
439             throw new moodle_exception('disabled', 'message');
440         }
442         if (empty($userid)) {
443             $userid = $USER->id;
444         }
446         // Validate context.
447         $context = context_system::instance();
448         self::validate_context($context);
450         $capability = 'moodle/site:manageallmessaging';
451         if (($USER->id != $userid) && !has_capability($capability, $context)) {
452             throw new required_capability_exception($context, $capability, 'nopermissions', '');
453         }
455         $params = array('userids' => $userids, 'userid' => $userid);
456         $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
458         foreach ($params['userids'] as $id) {
459             message_unblock_contact($id, $userid);
460         }
462         return null;
463     }
465     /**
466      * Unblock contacts return description.
467      *
468      * @return external_description
469      * @since Moodle 2.5
470      */
471     public static function unblock_contacts_returns() {
472         return null;
473     }
475     /**
476      * Return the structure of a message area contact.
477      *
478      * @return external_single_structure
479      * @since Moodle 3.2
480      */
481     private static function get_messagearea_contact_structure() {
482         return new external_single_structure(
483             array(
484                 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
485                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
486                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
487                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
488                 'ismessaging' => new external_value(PARAM_BOOL, 'If we are messaging the user'),
489                 'sentfromcurrentuser' => new external_value(PARAM_BOOL, 'Was the last message sent from the current user?'),
490                 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
491                 'messageid' => new external_value(PARAM_INT, 'The unique search message id', VALUE_DEFAULT, null),
492                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
493                 'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
494                 'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
495                 'unreadcount' => new external_value(PARAM_INT, 'The number of unread messages in this conversation',
496                     VALUE_DEFAULT, null),
497             )
498         );
499     }
501     /**
502      * Return the structure of a message area message.
503      *
504      * @return external_single_structure
505      * @since Moodle 3.2
506      */
507     private static function get_messagearea_message_structure() {
508         return new external_single_structure(
509             array(
510                 'id' => new external_value(PARAM_INT, 'The id of the message'),
511                 'useridfrom' => new external_value(PARAM_INT, 'The id of the user who sent the message'),
512                 'useridto' => new external_value(PARAM_INT, 'The id of the user who received the message'),
513                 'text' => new external_value(PARAM_RAW, 'The text of the message'),
514                 'displayblocktime' => new external_value(PARAM_BOOL, 'Should we display the block time?'),
515                 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
516                 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
517                 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
518                 'isread' => new external_value(PARAM_INT, 'Determines if the message was read or not'),
519             )
520         );
521     }
523     /**
524      * Get messagearea search users in course parameters.
525      *
526      * @return external_function_parameters
527      * @since 3.2
528      */
529     public static function data_for_messagearea_search_users_in_course_parameters() {
530         return new external_function_parameters(
531             array(
532                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
533                 'courseid' => new external_value(PARAM_INT, 'The id of the course'),
534                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
535                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
536                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
537             )
538         );
539     }
541     /**
542      * Get messagearea search users in course results.
543      *
544      * @param int $userid The id of the user who is performing the search
545      * @param int $courseid The id of the course
546      * @param string $search The string being searched
547      * @param int $limitfrom
548      * @param int $limitnum
549      * @return stdClass
550      * @throws moodle_exception
551      * @since 3.2
552      */
553     public static function data_for_messagearea_search_users_in_course($userid, $courseid, $search, $limitfrom = 0,
554                                                                        $limitnum = 0) {
555         global $CFG, $PAGE, $USER;
557         // Check if messaging is enabled.
558         if (empty($CFG->messaging)) {
559             throw new moodle_exception('disabled', 'message');
560         }
562         $systemcontext = context_system::instance();
564         $params = array(
565             'userid' => $userid,
566             'courseid' => $courseid,
567             'search' => $search,
568             'limitfrom' => $limitfrom,
569             'limitnum' => $limitnum
570         );
571         self::validate_parameters(self::data_for_messagearea_search_users_in_course_parameters(), $params);
572         self::validate_context($systemcontext);
574         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
575             throw new moodle_exception('You do not have permission to perform this action.');
576         }
578         $users = \core_message\api::search_users_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
579         $results = new \core_message\output\messagearea\user_search_results($users);
581         $renderer = $PAGE->get_renderer('core_message');
582         return $results->export_for_template($renderer);
583     }
585     /**
586      * Get messagearea search users in course returns.
587      *
588      * @return external_single_structure
589      * @since 3.2
590      */
591     public static function data_for_messagearea_search_users_in_course_returns() {
592         return new external_single_structure(
593             array(
594                 'contacts' => new external_multiple_structure(
595                     self::get_messagearea_contact_structure()
596                 ),
597             )
598         );
599     }
601     /**
602      * Get messagearea search users parameters.
603      *
604      * @return external_function_parameters
605      * @since 3.2
606      */
607     public static function data_for_messagearea_search_users_parameters() {
608         return new external_function_parameters(
609             array(
610                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
611                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
612                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
613             )
614         );
615     }
617     /**
618      * Get messagearea search users results.
619      *
620      * @param int $userid The id of the user who is performing the search
621      * @param string $search The string being searched
622      * @param int $limitnum
623      * @return stdClass
624      * @throws moodle_exception
625      * @since 3.2
626      */
627     public static function data_for_messagearea_search_users($userid, $search, $limitnum = 0) {
628         global $CFG, $PAGE, $USER;
630         // Check if messaging is enabled.
631         if (empty($CFG->messaging)) {
632             throw new moodle_exception('disabled', 'message');
633         }
635         $systemcontext = context_system::instance();
637         $params = array(
638             'userid' => $userid,
639             'search' => $search,
640             'limitnum' => $limitnum
641         );
642         self::validate_parameters(self::data_for_messagearea_search_users_parameters(), $params);
643         self::validate_context($systemcontext);
645         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
646             throw new moodle_exception('You do not have permission to perform this action.');
647         }
649         list($contacts, $courses, $noncontacts) = \core_message\api::search_users($userid, $search, $limitnum);
650         $search = new \core_message\output\messagearea\user_search_results($contacts, $courses, $noncontacts);
652         $renderer = $PAGE->get_renderer('core_message');
653         return $search->export_for_template($renderer);
654     }
656     /**
657      * Get messagearea search users returns.
658      *
659      * @return external_single_structure
660      * @since 3.2
661      */
662     public static function data_for_messagearea_search_users_returns() {
663         return new external_single_structure(
664             array(
665                 'contacts' => new external_multiple_structure(
666                     self::get_messagearea_contact_structure()
667                 ),
668                 'courses' => new external_multiple_structure(
669                     new external_single_structure(
670                         array(
671                             'id' => new external_value(PARAM_INT, 'The course id'),
672                             'shortname' => new external_value(PARAM_NOTAGS, 'The course shortname'),
673                             'fullname' => new external_value(PARAM_NOTAGS, 'The course fullname'),
674                         )
675                     )
676                 ),
677                 'noncontacts' => new external_multiple_structure(
678                     self::get_messagearea_contact_structure()
679                 )
680             )
681         );
682     }
684     /**
685      * Get messagearea search messages parameters.
686      *
687      * @return external_function_parameters
688      * @since 3.2
689      */
690     public static function data_for_messagearea_search_messages_parameters() {
691         return new external_function_parameters(
692             array(
693                 'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
694                 'search' => new external_value(PARAM_RAW, 'The string being searched'),
695                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
696                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
697             )
698         );
699     }
701     /**
702      * Get messagearea search messages results.
703      *
704      * @param int $userid The id of the user who is performing the search
705      * @param string $search The string being searched
706      * @param int $limitfrom
707      * @param int $limitnum
708      * @return stdClass
709      * @throws moodle_exception
710      * @since 3.2
711      */
712     public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
713         global $CFG, $PAGE, $USER;
715         // Check if messaging is enabled.
716         if (empty($CFG->messaging)) {
717             throw new moodle_exception('disabled', 'message');
718         }
720         $systemcontext = context_system::instance();
722         $params = array(
723             'userid' => $userid,
724             'search' => $search,
725             'limitfrom' => $limitfrom,
726             'limitnum' => $limitnum
728         );
729         self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
730         self::validate_context($systemcontext);
732         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
733             throw new moodle_exception('You do not have permission to perform this action.');
734         }
736         $messages = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
737         $results = new \core_message\output\messagearea\message_search_results($messages);
739         $renderer = $PAGE->get_renderer('core_message');
740         return $results->export_for_template($renderer);
741     }
743     /**
744      * Get messagearea search messages returns.
745      *
746      * @return external_single_structure
747      * @since 3.2
748      */
749     public static function data_for_messagearea_search_messages_returns() {
750         return new external_single_structure(
751             array(
752                 'contacts' => new external_multiple_structure(
753                     self::get_messagearea_contact_structure()
754                 )
755             )
756         );
757     }
759     /**
760      * The messagearea conversations parameters.
761      *
762      * @return external_function_parameters
763      * @since 3.2
764      */
765     public static function data_for_messagearea_conversations_parameters() {
766         return new external_function_parameters(
767             array(
768                 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
769                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
770                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
771             )
772         );
773     }
775     /**
776      * Get messagearea conversations.
777      *
778      * @param int $userid The id of the user who we are viewing conversations for
779      * @param int $limitfrom
780      * @param int $limitnum
781      * @return stdClass
782      * @throws moodle_exception
783      * @since 3.2
784      */
785     public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
786         global $CFG, $PAGE, $USER;
788         // Check if messaging is enabled.
789         if (empty($CFG->messaging)) {
790             throw new moodle_exception('disabled', 'message');
791         }
793         $systemcontext = context_system::instance();
795         $params = array(
796             'userid' => $userid,
797             'limitfrom' => $limitfrom,
798             'limitnum' => $limitnum
799         );
800         self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
801         self::validate_context($systemcontext);
803         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
804             throw new moodle_exception('You do not have permission to perform this action.');
805         }
807         $conversations = \core_message\api::get_conversations($userid, $limitfrom, $limitnum);
808         $conversations = new \core_message\output\messagearea\contacts(null, $conversations);
810         $renderer = $PAGE->get_renderer('core_message');
811         return $conversations->export_for_template($renderer);
812     }
814     /**
815      * The messagearea conversations return structure.
816      *
817      * @return external_single_structure
818      * @since 3.2
819      */
820     public static function data_for_messagearea_conversations_returns() {
821         return new external_single_structure(
822             array(
823                 'contacts' => new external_multiple_structure(
824                     self::get_messagearea_contact_structure()
825                 )
826             )
827         );
828     }
830     /**
831      * The messagearea contacts return parameters.
832      *
833      * @return external_function_parameters
834      * @since 3.2
835      */
836     public static function data_for_messagearea_contacts_parameters() {
837         return self::data_for_messagearea_conversations_parameters();
838     }
840     /**
841      * Get messagearea contacts parameters.
842      *
843      * @param int $userid The id of the user who we are viewing conversations for
844      * @param int $limitfrom
845      * @param int $limitnum
846      * @return stdClass
847      * @throws moodle_exception
848      * @since 3.2
849      */
850     public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
851         global $CFG, $PAGE, $USER;
853         // Check if messaging is enabled.
854         if (empty($CFG->messaging)) {
855             throw new moodle_exception('disabled', 'message');
856         }
858         $systemcontext = context_system::instance();
860         $params = array(
861             'userid' => $userid,
862             'limitfrom' => $limitfrom,
863             'limitnum' => $limitnum
864         );
865         self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
866         self::validate_context($systemcontext);
868         if (($USER->id != $userid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
869             throw new moodle_exception('You do not have permission to perform this action.');
870         }
872         $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
873         $contacts = new \core_message\output\messagearea\contacts(null, $contacts);
875         $renderer = $PAGE->get_renderer('core_message');
876         return $contacts->export_for_template($renderer);
877     }
879     /**
880      * The messagearea contacts return structure.
881      *
882      * @return external_single_structure
883      * @since 3.2
884      */
885     public static function data_for_messagearea_contacts_returns() {
886         return self::data_for_messagearea_conversations_returns();
887     }
889     /**
890      * The messagearea messages parameters.
891      *
892      * @return external_function_parameters
893      * @since 3.2
894      */
895     public static function data_for_messagearea_messages_parameters() {
896         return new external_function_parameters(
897             array(
898                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
899                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
900                 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
901                 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
902                 'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
903             )
904         );
905     }
907     /**
908      * Get messagearea messages.
909      *
910      * @param int $currentuserid The current user's id
911      * @param int $otheruserid The other user's id
912      * @param int $limitfrom
913      * @param int $limitnum
914      * @param boolean $newest
915      * @return stdClass
916      * @throws moodle_exception
917      * @since 3.2
918      */
919     public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
920                                                          $newest = false) {
921         global $CFG, $PAGE, $USER;
923         // Check if messaging is enabled.
924         if (empty($CFG->messaging)) {
925             throw new moodle_exception('disabled', 'message');
926         }
928         $systemcontext = context_system::instance();
930         $params = array(
931             'currentuserid' => $currentuserid,
932             'otheruserid' => $otheruserid,
933             'limitfrom' => $limitfrom,
934             'limitnum' => $limitnum,
935             'newest' => $newest
936         );
937         self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
938         self::validate_context($systemcontext);
940         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
941             throw new moodle_exception('You do not have permission to perform this action.');
942         }
944         if ($newest) {
945             $sort = 'timecreated DESC';
946         } else {
947             $sort = 'timecreated ASC';
948         }
949         $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom, $limitnum, $sort);
950         $messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
952         $renderer = $PAGE->get_renderer('core_message');
953         return $messages->export_for_template($renderer);
954     }
956     /**
957      * The messagearea messages return structure.
958      *
959      * @return external_single_structure
960      * @since 3.2
961      */
962     public static function data_for_messagearea_messages_returns() {
963         return new external_single_structure(
964             array(
965                 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing
966                     the messages on behalf of?'),
967                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
968                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
969                 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
970                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
971                 'messages' => new external_multiple_structure(
972                     self::get_messagearea_message_structure()
973                 ),
974                 'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
975             )
976         );
977     }
979     /**
980      * The get most recent message return parameters.
981      *
982      * @return external_function_parameters
983      * @since 3.2
984      */
985     public static function data_for_messagearea_get_most_recent_message_parameters() {
986         return new external_function_parameters(
987             array(
988                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
989                 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
990             )
991         );
992     }
994     /**
995      * Get the most recent message in a conversation.
996      *
997      * @param int $currentuserid The current user's id
998      * @param int $otheruserid The other user's id
999      * @return stdClass
1000      * @throws moodle_exception
1001      * @since 3.2
1002      */
1003     public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
1004         global $CFG, $PAGE, $USER;
1006         // Check if messaging is enabled.
1007         if (empty($CFG->messaging)) {
1008             throw new moodle_exception('disabled', 'message');
1009         }
1011         $systemcontext = context_system::instance();
1013         $params = array(
1014             'currentuserid' => $currentuserid,
1015             'otheruserid' => $otheruserid
1016         );
1017         self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
1018         self::validate_context($systemcontext);
1020         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1021             throw new moodle_exception('You do not have permission to perform this action.');
1022         }
1024         $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
1025         $message = new \core_message\output\messagearea\message($message);
1027         $renderer = $PAGE->get_renderer('core_message');
1028         return $message->export_for_template($renderer);
1029     }
1031     /**
1032      * The get most recent message return structure.
1033      *
1034      * @return external_single_structure
1035      * @since 3.2
1036      */
1037     public static function data_for_messagearea_get_most_recent_message_returns() {
1038         return self::get_messagearea_message_structure();
1039     }
1041     /**
1042      * The get profile parameters.
1043      *
1044      * @return external_function_parameters
1045      * @since 3.2
1046      */
1047     public static function data_for_messagearea_get_profile_parameters() {
1048         return new external_function_parameters(
1049             array(
1050                 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
1051                 'otheruserid' => new external_value(PARAM_INT, 'The id of the user whose profile we want to view'),
1052             )
1053         );
1054     }
1056     /**
1057      * Get the profile information for a contact.
1058      *
1059      * @param int $currentuserid The current user's id
1060      * @param int $otheruserid The id of the user whose profile we are viewing
1061      * @return stdClass
1062      * @throws moodle_exception
1063      * @since 3.2
1064      */
1065     public static function data_for_messagearea_get_profile($currentuserid, $otheruserid) {
1066         global $CFG, $PAGE, $USER;
1068         // Check if messaging is enabled.
1069         if (empty($CFG->messaging)) {
1070             throw new moodle_exception('disabled', 'message');
1071         }
1073         $systemcontext = context_system::instance();
1075         $params = array(
1076             'currentuserid' => $currentuserid,
1077             'otheruserid' => $otheruserid
1078         );
1079         self::validate_parameters(self::data_for_messagearea_get_profile_parameters(), $params);
1080         self::validate_context($systemcontext);
1082         if (($USER->id != $currentuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) {
1083             throw new moodle_exception('You do not have permission to perform this action.');
1084         }
1086         $profile = \core_message\api::get_profile($currentuserid, $otheruserid);
1087         $profile = new \core_message\output\messagearea\profile($profile);
1089         $renderer = $PAGE->get_renderer('core_message');
1090         return $profile->export_for_template($renderer);
1091     }
1093     /**
1094      * The get profile return structure.
1095      *
1096      * @return external_single_structure
1097      * @since 3.2
1098      */
1099     public static function data_for_messagearea_get_profile_returns() {
1100         return new external_single_structure(
1101             array(
1102                 'userid' => new external_value(PARAM_INT, 'The id of the user whose profile we are viewing'),
1103                 'email' => new external_value(core_user::get_property_type('email'), 'An email address'),
1104                 'country' => new external_value(PARAM_TEXT, 'Home country of the user'),
1105                 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user'),
1106                 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
1107                 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
1108                 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
1109                 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
1110                 'isblocked' => new external_value(PARAM_BOOL, 'Is the user blocked?'),
1111                 'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?')
1112             )
1113         );
1114     }
1116     /**
1117      * Get contacts parameters description.
1118      *
1119      * @return external_function_parameters
1120      * @since Moodle 2.5
1121      */
1122     public static function get_contacts_parameters() {
1123         return new external_function_parameters(array());
1124     }
1126     /**
1127      * Get contacts.
1128      *
1129      * @return external_description
1130      * @since Moodle 2.5
1131      */
1132     public static function get_contacts() {
1133         global $CFG, $PAGE;
1135         // Check if messaging is enabled.
1136         if (empty($CFG->messaging)) {
1137             throw new moodle_exception('disabled', 'message');
1138         }
1140         require_once($CFG->dirroot . '/user/lib.php');
1142         list($online, $offline, $strangers) = message_get_contacts();
1143         $allcontacts = array('online' => $online, 'offline' => $offline, 'strangers' => $strangers);
1144         foreach ($allcontacts as $mode => $contacts) {
1145             foreach ($contacts as $key => $contact) {
1146                 $newcontact = array(
1147                     'id' => $contact->id,
1148                     'fullname' => fullname($contact),
1149                     'unread' => $contact->messagecount
1150                 );
1152                 $userpicture = new user_picture($contact);
1153                 $userpicture->size = 1; // Size f1.
1154                 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1155                 $userpicture->size = 0; // Size f2.
1156                 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1158                 $allcontacts[$mode][$key] = $newcontact;
1159             }
1160         }
1161         return $allcontacts;
1162     }
1164     /**
1165      * Get contacts return description.
1166      *
1167      * @return external_description
1168      * @since Moodle 2.5
1169      */
1170     public static function get_contacts_returns() {
1171         return new external_single_structure(
1172             array(
1173                 'online' => new external_multiple_structure(
1174                     new external_single_structure(
1175                         array(
1176                             'id' => new external_value(PARAM_INT, 'User ID'),
1177                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1178                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1179                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1180                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1181                         )
1182                     ),
1183                     'List of online contacts'
1184                 ),
1185                 'offline' => new external_multiple_structure(
1186                     new external_single_structure(
1187                         array(
1188                             'id' => new external_value(PARAM_INT, 'User ID'),
1189                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1190                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1191                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1192                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1193                         )
1194                     ),
1195                     'List of offline contacts'
1196                 ),
1197                 'strangers' => new external_multiple_structure(
1198                     new external_single_structure(
1199                         array(
1200                             'id' => new external_value(PARAM_INT, 'User ID'),
1201                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1202                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1203                             'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
1204                             'unread' => new external_value(PARAM_INT, 'Unread message count')
1205                         )
1206                     ),
1207                     'List of users that are not in the user\'s contact list but have sent a message'
1208                 )
1209             )
1210         );
1211     }
1213     /**
1214      * Search contacts parameters description.
1215      *
1216      * @return external_function_parameters
1217      * @since Moodle 2.5
1218      */
1219     public static function search_contacts_parameters() {
1220         return new external_function_parameters(
1221             array(
1222                 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
1223                 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
1224                     VALUE_DEFAULT, false)
1225             )
1226         );
1227     }
1229     /**
1230      * Search contacts.
1231      *
1232      * @param string $searchtext query string.
1233      * @param bool $onlymycourses limit the search to the user's courses only.
1234      * @return external_description
1235      * @since Moodle 2.5
1236      */
1237     public static function search_contacts($searchtext, $onlymycourses = false) {
1238         global $CFG, $USER, $PAGE;
1239         require_once($CFG->dirroot . '/user/lib.php');
1241         // Check if messaging is enabled.
1242         if (empty($CFG->messaging)) {
1243             throw new moodle_exception('disabled', 'message');
1244         }
1246         require_once($CFG->libdir . '/enrollib.php');
1248         $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
1249         $params = self::validate_parameters(self::search_contacts_parameters(), $params);
1251         // Extra validation, we do not allow empty queries.
1252         if ($params['searchtext'] === '') {
1253             throw new moodle_exception('querystringcannotbeempty');
1254         }
1256         $courseids = array();
1257         if ($params['onlymycourses']) {
1258             $mycourses = enrol_get_my_courses(array('id'));
1259             foreach ($mycourses as $mycourse) {
1260                 $courseids[] = $mycourse->id;
1261             }
1262         } else {
1263             $courseids[] = SITEID;
1264         }
1266         // Retrieving the users matching the query.
1267         $users = message_search_users($courseids, $params['searchtext']);
1268         $results = array();
1269         foreach ($users as $user) {
1270             $results[$user->id] = $user;
1271         }
1273         // Reorganising information.
1274         foreach ($results as &$user) {
1275             $newuser = array(
1276                 'id' => $user->id,
1277                 'fullname' => fullname($user)
1278             );
1280             // Avoid undefined property notice as phone not specified.
1281             $user->phone1 = null;
1282             $user->phone2 = null;
1284             $userpicture = new user_picture($user);
1285             $userpicture->size = 1; // Size f1.
1286             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1287             $userpicture->size = 0; // Size f2.
1288             $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
1290             $user = $newuser;
1291         }
1293         return $results;
1294     }
1296     /**
1297      * Search contacts return description.
1298      *
1299      * @return external_description
1300      * @since Moodle 2.5
1301      */
1302     public static function search_contacts_returns() {
1303         return new external_multiple_structure(
1304             new external_single_structure(
1305                 array(
1306                     'id' => new external_value(PARAM_INT, 'User ID'),
1307                     'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1308                     'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
1309                     'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
1310                 )
1311             ),
1312             'List of contacts'
1313         );
1314     }
1316     /**
1317      * Get messages parameters description.
1318      *
1319      * @return external_function_parameters
1320      * @since 2.8
1321      */
1322     public static function get_messages_parameters() {
1323         return new external_function_parameters(
1324             array(
1325                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1326                 'useridfrom' => new external_value(
1327                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1328                     VALUE_DEFAULT, 0),
1329                 'type' => new external_value(
1330                     PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
1331                     VALUE_DEFAULT, 'both'),
1332                 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
1333                 'newestfirst' => new external_value(
1334                     PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
1335                     VALUE_DEFAULT, true),
1336                 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
1337                 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
1338             )
1339         );
1340     }
1342     /**
1343      * Get messages function implementation.
1344      *
1345      * @since  2.8
1346      * @throws invalid_parameter_exception
1347      * @throws moodle_exception
1348      * @param  int      $useridto       the user id who received the message
1349      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
1350      * @param  string   $type           type of message to return, expected values: notifications, conversations and both
1351      * @param  bool     $read           true for retreiving read messages, false for unread
1352      * @param  bool     $newestfirst    true for ordering by newest first, false for oldest first
1353      * @param  int      $limitfrom      limit from
1354      * @param  int      $limitnum       limit num
1355      * @return external_description
1356      */
1357     public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
1358                                         $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
1359         global $CFG, $USER;
1361         $warnings = array();
1363         $params = array(
1364             'useridto' => $useridto,
1365             'useridfrom' => $useridfrom,
1366             'type' => $type,
1367             'read' => $read,
1368             'newestfirst' => $newestfirst,
1369             'limitfrom' => $limitfrom,
1370             'limitnum' => $limitnum
1371         );
1373         $params = self::validate_parameters(self::get_messages_parameters(), $params);
1375         $context = context_system::instance();
1376         self::validate_context($context);
1378         $useridto = $params['useridto'];
1379         $useridfrom = $params['useridfrom'];
1380         $type = $params['type'];
1381         $read = $params['read'];
1382         $newestfirst = $params['newestfirst'];
1383         $limitfrom = $params['limitfrom'];
1384         $limitnum = $params['limitnum'];
1386         $allowedvalues = array('notifications', 'conversations', 'both');
1387         if (!in_array($type, $allowedvalues)) {
1388             throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
1389                 'allowed values are: ' . implode(',', $allowedvalues));
1390         }
1392         // Check if private messaging between users is allowed.
1393         if (empty($CFG->messaging)) {
1394             // If we are retreiving only conversations, and messaging is disabled, throw an exception.
1395             if ($type == "conversations") {
1396                 throw new moodle_exception('disabled', 'message');
1397             }
1398             if ($type == "both") {
1399                 $warning = array();
1400                 $warning['item'] = 'message';
1401                 $warning['itemid'] = $USER->id;
1402                 $warning['warningcode'] = '1';
1403                 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
1404                     Only notifications will be returned';
1405                 $warnings[] = $warning;
1406             }
1407         }
1409         if (!empty($useridto)) {
1410             if (core_user::is_real_user($useridto)) {
1411                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1412             } else {
1413                 throw new moodle_exception('invaliduser');
1414             }
1415         }
1417         if (!empty($useridfrom)) {
1418             // We use get_user here because the from user can be the noreply or support user.
1419             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1420         }
1422         // Check if the current user is the sender/receiver or just a privileged user.
1423         if ($useridto != $USER->id and $useridfrom != $USER->id and
1424              !has_capability('moodle/site:readallmessages', $context)) {
1425             throw new moodle_exception('accessdenied', 'admin');
1426         }
1428         // Which type of messages to retrieve.
1429         $notifications = -1;
1430         if ($type != 'both') {
1431             $notifications = ($type == 'notifications') ? 1 : 0;
1432         }
1434         $orderdirection = $newestfirst ? 'DESC' : 'ASC';
1435         $sort = "mr.timecreated $orderdirection";
1437         if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
1438             $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
1440             // In some cases, we don't need to get the to/from user objects from the sql query.
1441             $userfromfullname = '';
1442             $usertofullname = '';
1444             // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
1445             if (!empty($useridto)) {
1446                 $usertofullname = fullname($userto, $canviewfullname);
1447                 // The user from may or may not be filled.
1448                 if (!empty($useridfrom)) {
1449                     $userfromfullname = fullname($userfrom, $canviewfullname);
1450                 }
1451             } else {
1452                 // If the useridto field is empty, the useridfrom must be filled.
1453                 $userfromfullname = fullname($userfrom, $canviewfullname);
1454             }
1455             foreach ($messages as $mid => $message) {
1457                 // Do not return deleted messages.
1458                 if (($useridto == $USER->id and $message->timeusertodeleted) or
1459                         ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
1461                     unset($messages[$mid]);
1462                     continue;
1463                 }
1465                 // We need to get the user from the query.
1466                 if (empty($userfromfullname)) {
1467                     // Check for non-reply and support users.
1468                     if (core_user::is_real_user($message->useridfrom)) {
1469                         $user = new stdClass();
1470                         $user = username_load_fields_from_object($user, $message, 'userfrom');
1471                         $message->userfromfullname = fullname($user, $canviewfullname);
1472                     } else {
1473                         $user = core_user::get_user($message->useridfrom);
1474                         $message->userfromfullname = fullname($user, $canviewfullname);
1475                     }
1476                 } else {
1477                     $message->userfromfullname = $userfromfullname;
1478                 }
1480                 // We need to get the user from the query.
1481                 if (empty($usertofullname)) {
1482                     $user = new stdClass();
1483                     $user = username_load_fields_from_object($user, $message, 'userto');
1484                     $message->usertofullname = fullname($user, $canviewfullname);
1485                 } else {
1486                     $message->usertofullname = $usertofullname;
1487                 }
1489                 // This field is only available in the message_read table.
1490                 if (!isset($message->timeread)) {
1491                     $message->timeread = 0;
1492                 }
1494                 $message->text = message_format_message_text($message);
1495                 $messages[$mid] = (array) $message;
1496             }
1497         }
1499         $results = array(
1500             'messages' => $messages,
1501             'warnings' => $warnings
1502         );
1504         return $results;
1505     }
1507     /**
1508      * Get messages return description.
1509      *
1510      * @return external_single_structure
1511      * @since 2.8
1512      */
1513     public static function get_messages_returns() {
1514         return new external_single_structure(
1515             array(
1516                 'messages' => new external_multiple_structure(
1517                     new external_single_structure(
1518                         array(
1519                             'id' => new external_value(PARAM_INT, 'Message id'),
1520                             'useridfrom' => new external_value(PARAM_INT, 'User from id'),
1521                             'useridto' => new external_value(PARAM_INT, 'User to id'),
1522                             'subject' => new external_value(PARAM_TEXT, 'The message subject'),
1523                             'text' => new external_value(PARAM_RAW, 'The message text formated'),
1524                             'fullmessage' => new external_value(PARAM_RAW, 'The message'),
1525                             'fullmessageformat' => new external_format_value('fullmessage'),
1526                             'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
1527                             'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
1528                             'notification' => new external_value(PARAM_INT, 'Is a notification?'),
1529                             'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
1530                             'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
1531                             'timecreated' => new external_value(PARAM_INT, 'Time created'),
1532                             'timeread' => new external_value(PARAM_INT, 'Time read'),
1533                             'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
1534                             'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
1535                         ), 'message'
1536                     )
1537                 ),
1538                 'warnings' => new external_warnings()
1539             )
1540         );
1541     }
1543     /**
1544      * Mark all notifications as read parameters description.
1545      *
1546      * @return external_function_parameters
1547      * @since 3.2
1548      */
1549     public static function mark_all_notifications_as_read_parameters() {
1550         return new external_function_parameters(
1551             array(
1552                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1553                 'useridfrom' => new external_value(
1554                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1555                     VALUE_DEFAULT, 0),
1556             )
1557         );
1558     }
1560     /**
1561      * Mark all notifications as read function.
1562      *
1563      * @since  3.2
1564      * @throws invalid_parameter_exception
1565      * @throws moodle_exception
1566      * @param  int      $useridto       the user id who received the message
1567      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
1568      * @return external_description
1569      */
1570     public static function mark_all_notifications_as_read($useridto, $useridfrom) {
1571         global $USER;
1573         $params = self::validate_parameters(
1574             self::mark_all_notifications_as_read_parameters(),
1575             array(
1576                 'useridto' => $useridto,
1577                 'useridfrom' => $useridfrom,
1578             )
1579         );
1581         $context = context_system::instance();
1582         self::validate_context($context);
1584         $useridto = $params['useridto'];
1585         $useridfrom = $params['useridfrom'];
1587         if (!empty($useridto)) {
1588             if (core_user::is_real_user($useridto)) {
1589                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1590             } else {
1591                 throw new moodle_exception('invaliduser');
1592             }
1593         }
1595         if (!empty($useridfrom)) {
1596             // We use get_user here because the from user can be the noreply or support user.
1597             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1598         }
1600         // Check if the current user is the sender/receiver or just a privileged user.
1601         if ($useridto != $USER->id and $useridfrom != $USER->id and
1602             // The deleteanymessage cap seems more reasonable here than readallmessages.
1603              !has_capability('moodle/site:deleteanymessage', $context)) {
1604             throw new moodle_exception('accessdenied', 'admin');
1605         }
1607         \core_message\api::mark_all_read_for_user($useridto, $useridfrom, MESSAGE_TYPE_NOTIFICATION);
1609         return true;
1610     }
1612     /**
1613      * Mark all notifications as read return description.
1614      *
1615      * @return external_single_structure
1616      * @since 3.2
1617      */
1618     public static function mark_all_notifications_as_read_returns() {
1619         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
1620     }
1622     /**
1623      * Get unread conversations count parameters description.
1624      *
1625      * @return external_function_parameters
1626      * @since 3.2
1627      */
1628     public static function get_unread_conversations_count_parameters() {
1629         return new external_function_parameters(
1630             array(
1631                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1632             )
1633         );
1634     }
1636     /**
1637      * Get unread messages count function.
1638      *
1639      * @since  3.2
1640      * @throws invalid_parameter_exception
1641      * @throws moodle_exception
1642      * @param  int      $useridto       the user id who received the message
1643      * @return external_description
1644      */
1645     public static function get_unread_conversations_count($useridto) {
1646         global $USER, $CFG;
1648         // Check if messaging is enabled.
1649         if (empty($CFG->messaging)) {
1650             throw new moodle_exception('disabled', 'message');
1651         }
1653         $params = self::validate_parameters(
1654             self::get_unread_conversations_count_parameters(),
1655             array('useridto' => $useridto)
1656         );
1658         $context = context_system::instance();
1659         self::validate_context($context);
1661         $useridto = $params['useridto'];
1663         if (!empty($useridto)) {
1664             if (core_user::is_real_user($useridto)) {
1665                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1666             } else {
1667                 throw new moodle_exception('invaliduser');
1668             }
1669         } else {
1670             $useridto = $USER->id;
1671         }
1673         // Check if the current user is the receiver or just a privileged user.
1674         if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
1675             throw new moodle_exception('accessdenied', 'admin');
1676         }
1678         return \core_message\api::count_unread_conversations($userto);
1679     }
1681     /**
1682      * Get unread conversations count return description.
1683      *
1684      * @return external_single_structure
1685      * @since 3.2
1686      */
1687     public static function get_unread_conversations_count_returns() {
1688         return new external_value(PARAM_INT, 'The count of unread messages for the user');
1689     }
1691     /**
1692      * Get blocked users parameters description.
1693      *
1694      * @return external_function_parameters
1695      * @since 2.9
1696      */
1697     public static function get_blocked_users_parameters() {
1698         return new external_function_parameters(
1699             array(
1700                 'userid' => new external_value(PARAM_INT,
1701                                 'the user whose blocked users we want to retrieve',
1702                                 VALUE_REQUIRED),
1703             )
1704         );
1705     }
1707     /**
1708      * Retrieve a list of users blocked
1709      *
1710      * @param  int $userid the user whose blocked users we want to retrieve
1711      * @return external_description
1712      * @since 2.9
1713      */
1714     public static function get_blocked_users($userid) {
1715         global $CFG, $USER, $PAGE;
1717         // Warnings array, it can be empty at the end but is mandatory.
1718         $warnings = array();
1720         // Validate params.
1721         $params = array(
1722             'userid' => $userid
1723         );
1724         $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
1725         $userid = $params['userid'];
1727         // Validate context.
1728         $context = context_system::instance();
1729         self::validate_context($context);
1731         // Check if private messaging between users is allowed.
1732         if (empty($CFG->messaging)) {
1733             throw new moodle_exception('disabled', 'message');
1734         }
1736         $user = core_user::get_user($userid, '*', MUST_EXIST);
1737         core_user::require_active_user($user);
1739         // Check if we have permissions for retrieve the information.
1740         $capability = 'moodle/site:manageallmessaging';
1741         if (($USER->id != $userid) && !has_capability($capability, $context)) {
1742             throw new required_capability_exception($context, $capability, 'nopermissions', '');
1743         }
1745         // Now, we can get safely all the blocked users.
1746         $users = message_get_blocked_users($user);
1748         $blockedusers = array();
1749         foreach ($users as $user) {
1750             $newuser = array(
1751                 'id' => $user->id,
1752                 'fullname' => fullname($user),
1753             );
1755             $userpicture = new user_picture($user);
1756             $userpicture->size = 1; // Size f1.
1757             $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
1759             $blockedusers[] = $newuser;
1760         }
1762         $results = array(
1763             'users' => $blockedusers,
1764             'warnings' => $warnings
1765         );
1766         return $results;
1767     }
1769     /**
1770      * Get blocked users return description.
1771      *
1772      * @return external_single_structure
1773      * @since 2.9
1774      */
1775     public static function get_blocked_users_returns() {
1776         return new external_single_structure(
1777             array(
1778                 'users' => new external_multiple_structure(
1779                     new external_single_structure(
1780                         array(
1781                             'id' => new external_value(PARAM_INT, 'User ID'),
1782                             'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1783                             'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
1784                         )
1785                     ),
1786                     'List of blocked users'
1787                 ),
1788                 'warnings' => new external_warnings()
1789             )
1790         );
1791     }
1793     /**
1794      * Returns description of method parameters
1795      *
1796      * @return external_function_parameters
1797      * @since 2.9
1798      */
1799     public static function mark_message_read_parameters() {
1800         return new external_function_parameters(
1801             array(
1802                 'messageid' => new external_value(PARAM_INT, 'id of the message (in the message table)'),
1803                 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read',
1804                     VALUE_DEFAULT, 0)
1805             )
1806         );
1807     }
1809     /**
1810      * Mark a single message as read, trigger message_viewed event
1811      *
1812      * @param  int $messageid id of the message (in the message table)
1813      * @param  int $timeread timestamp for when the message should be marked read
1814      * @return external_description
1815      * @throws invalid_parameter_exception
1816      * @throws moodle_exception
1817      * @since 2.9
1818      */
1819     public static function mark_message_read($messageid, $timeread) {
1820         global $CFG, $DB, $USER;
1822         // Check if private messaging between users is allowed.
1823         if (empty($CFG->messaging)) {
1824             throw new moodle_exception('disabled', 'message');
1825         }
1827         // Warnings array, it can be empty at the end but is mandatory.
1828         $warnings = array();
1830         // Validate params.
1831         $params = array(
1832             'messageid' => $messageid,
1833             'timeread' => $timeread
1834         );
1835         $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
1837         if (empty($params['timeread'])) {
1838             $timeread = time();
1839         } else {
1840             $timeread = $params['timeread'];
1841         }
1843         // Validate context.
1844         $context = context_system::instance();
1845         self::validate_context($context);
1847         $message = $DB->get_record('message', array('id' => $params['messageid']), '*', MUST_EXIST);
1849         if ($message->useridto != $USER->id) {
1850             throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
1851         }
1853         $messageid = message_mark_message_read($message, $timeread);
1855         $results = array(
1856             'messageid' => $messageid,
1857             'warnings' => $warnings
1858         );
1859         return $results;
1860     }
1862     /**
1863      * Returns description of method result value
1864      *
1865      * @return external_description
1866      * @since 2.9
1867      */
1868     public static function mark_message_read_returns() {
1869         return new external_single_structure(
1870             array(
1871                 'messageid' => new external_value(PARAM_INT, 'the id of the message in the message_read table'),
1872                 'warnings' => new external_warnings()
1873             )
1874         );
1875     }
1877     /**
1878      * Mark all messages as read parameters description.
1879      *
1880      * @return external_function_parameters
1881      * @since 3.2
1882      */
1883     public static function mark_all_messages_as_read_parameters() {
1884         return new external_function_parameters(
1885             array(
1886                 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
1887                 'useridfrom' => new external_value(
1888                     PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
1889                     VALUE_DEFAULT, 0),
1890             )
1891         );
1892     }
1894     /**
1895      * Mark all notifications as read function.
1896      *
1897      * @since  3.2
1898      * @throws invalid_parameter_exception
1899      * @throws moodle_exception
1900      * @param  int      $useridto       the user id who received the message
1901      * @param  int      $useridfrom     the user id who send the message. -10 or -20 for no-reply or support user
1902      * @return external_description
1903      */
1904     public static function mark_all_messages_as_read($useridto, $useridfrom) {
1905         global $USER, $CFG;
1907         // Check if messaging is enabled.
1908         if (empty($CFG->messaging)) {
1909             throw new moodle_exception('disabled', 'message');
1910         }
1912         $params = self::validate_parameters(
1913             self::mark_all_messages_as_read_parameters(),
1914             array(
1915                 'useridto' => $useridto,
1916                 'useridfrom' => $useridfrom,
1917             )
1918         );
1920         $context = context_system::instance();
1921         self::validate_context($context);
1923         $useridto = $params['useridto'];
1924         $useridfrom = $params['useridfrom'];
1926         if (!empty($useridto)) {
1927             if (core_user::is_real_user($useridto)) {
1928                 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
1929             } else {
1930                 throw new moodle_exception('invaliduser');
1931             }
1932         }
1934         if (!empty($useridfrom)) {
1935             // We use get_user here because the from user can be the noreply or support user.
1936             $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
1937         }
1939         // Check if the current user is the sender/receiver or just a privileged user.
1940         if ($useridto != $USER->id and $useridfrom != $USER->id and
1941             // The deleteanymessage cap seems more reasonable here than readallmessages.
1942              !has_capability('moodle/site:deleteanymessage', $context)) {
1943             throw new moodle_exception('accessdenied', 'admin');
1944         }
1946         \core_message\api::mark_all_read_for_user($useridto, $useridfrom, MESSAGE_TYPE_MESSAGE);
1948         return true;
1949     }
1951     /**
1952      * Mark all notifications as read return description.
1953      *
1954      * @return external_single_structure
1955      * @since 3.2
1956      */
1957     public static function mark_all_messages_as_read_returns() {
1958         return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise');
1959     }
1961     /**
1962      * Returns description of method parameters.
1963      *
1964      * @return external_function_parameters
1965      * @since 3.2
1966      */
1967     public static function delete_conversation_parameters() {
1968         return new external_function_parameters(
1969             array(
1970                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'),
1971                 'otheruserid' => new external_value(PARAM_INT, 'The user id of the other user in the conversation'),
1972             )
1973         );
1974     }
1976     /**
1977      * Deletes a conversation.
1978      *
1979      * @param int $userid The user id of who we want to delete the conversation for
1980      * @param int $otheruserid The user id of the other user in the conversation
1981      * @return array
1982      * @throws moodle_exception
1983      * @since 3.2
1984      */
1985     public static function delete_conversation($userid, $otheruserid) {
1986         global $CFG;
1988         // Check if private messaging between users is allowed.
1989         if (empty($CFG->messaging)) {
1990             throw new moodle_exception('disabled', 'message');
1991         }
1993         // Warnings array, it can be empty at the end but is mandatory.
1994         $warnings = array();
1996         // Validate params.
1997         $params = array(
1998             'userid' => $userid,
1999             'otheruserid' => $otheruserid,
2000         );
2001         $params = self::validate_parameters(self::delete_conversation_parameters(), $params);
2003         // Validate context.
2004         $context = context_system::instance();
2005         self::validate_context($context);
2007         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2008         core_user::require_active_user($user);
2010         if (\core_message\api::can_delete_conversation($user->id)) {
2011             $status = \core_message\api::delete_conversation($user->id, $otheruserid);
2012         } else {
2013             throw new moodle_exception('You do not have permission to delete messages');
2014         }
2016         $results = array(
2017             'status' => $status,
2018             'warnings' => $warnings
2019         );
2021         return $results;
2022     }
2024     /**
2025      * Returns description of method result value.
2026      *
2027      * @return external_description
2028      * @since 3.2
2029      */
2030     public static function delete_conversation_returns() {
2031         return new external_single_structure(
2032             array(
2033                 'status' => new external_value(PARAM_BOOL, 'True if the conversation was deleted, false otherwise'),
2034                 'warnings' => new external_warnings()
2035             )
2036         );
2037     }
2039     /**
2040      * Returns description of method parameters
2041      *
2042      * @return external_function_parameters
2043      * @since 3.1
2044      */
2045     public static function delete_message_parameters() {
2046         return new external_function_parameters(
2047             array(
2048                 'messageid' => new external_value(PARAM_INT, 'The message id'),
2049                 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
2050                 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
2051             )
2052         );
2053     }
2055     /**
2056      * Deletes a message
2057      *
2058      * @param  int $messageid the message id
2059      * @param  int $userid the user id of who we want to delete the message for
2060      * @param  bool $read if is a message read (default to true)
2061      * @return external_description
2062      * @throws moodle_exception
2063      * @since 3.1
2064      */
2065     public static function delete_message($messageid, $userid, $read = true) {
2066         global $CFG, $DB;
2068         // Check if private messaging between users is allowed.
2069         if (empty($CFG->messaging)) {
2070             throw new moodle_exception('disabled', 'message');
2071         }
2073         // Warnings array, it can be empty at the end but is mandatory.
2074         $warnings = array();
2076         // Validate params.
2077         $params = array(
2078             'messageid' => $messageid,
2079             'userid' => $userid,
2080             'read' => $read
2081         );
2082         $params = self::validate_parameters(self::delete_message_parameters(), $params);
2084         // Validate context.
2085         $context = context_system::instance();
2086         self::validate_context($context);
2088         $messagestable = $params['read'] ? 'message_read' : 'message';
2089         $message = $DB->get_record($messagestable, array('id' => $params['messageid']), '*', MUST_EXIST);
2091         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2092         core_user::require_active_user($user);
2094         $status = false;
2095         if (message_can_delete_message($message, $user->id)) {
2096             $status = message_delete_message($message, $user->id);;
2097         } else {
2098             throw new moodle_exception('You do not have permission to delete this message');
2099         }
2101         $results = array(
2102             'status' => $status,
2103             'warnings' => $warnings
2104         );
2105         return $results;
2106     }
2108     /**
2109      * Returns description of method result value
2110      *
2111      * @return external_description
2112      * @since 3.1
2113      */
2114     public static function delete_message_returns() {
2115         return new external_single_structure(
2116             array(
2117                 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
2118                 'warnings' => new external_warnings()
2119             )
2120         );
2121     }
2123     /**
2124      * Returns description of method parameters
2125      *
2126      * @return external_function_parameters
2127      * @since 3.2
2128      */
2129     public static function message_processor_config_form_parameters() {
2130         return new external_function_parameters(
2131             array(
2132                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED),
2133                 'name' => new external_value(PARAM_TEXT, 'The name of the message processor'),
2134                 'formvalues' => new external_multiple_structure(
2135                     new external_single_structure(
2136                         array(
2137                             'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED),
2138                             'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED),
2139                         )
2140                     ),
2141                     'Config form values',
2142                     VALUE_REQUIRED
2143                 ),
2144             )
2145         );
2146     }
2148     /**
2149      * Processes a message processor config form.
2150      *
2151      * @param  int $userid the user id
2152      * @param  string $name the name of the processor
2153      * @param  array $formvalues the form values
2154      * @return external_description
2155      * @throws moodle_exception
2156      * @since 3.2
2157      */
2158     public static function message_processor_config_form($userid, $name, $formvalues) {
2159         global $USER, $CFG;
2161         // Check if messaging is enabled.
2162         if (empty($CFG->messaging)) {
2163             throw new moodle_exception('disabled', 'message');
2164         }
2166         $params = self::validate_parameters(
2167             self::message_processor_config_form_parameters(),
2168             array(
2169                 'userid' => $userid,
2170                 'name' => $name,
2171                 'formvalues' => $formvalues,
2172             )
2173         );
2175         if (empty($params['userid'])) {
2176             $params['userid'] = $USER->id;
2177         }
2179         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2180         core_user::require_active_user($user);
2182         $processor = get_message_processor($name);
2183         $preferences = [];
2184         $form = new stdClass();
2186         foreach ($formvalues as $formvalue) {
2187             // Curly braces to ensure interpretation is consistent between
2188             // php 5 and php 7.
2189             $form->{$formvalue['name']} = $formvalue['value'];
2190         }
2192         $processor->process_form($form, $preferences);
2194         if (!empty($preferences)) {
2195             set_user_preferences($preferences, $userid);
2196         }
2197     }
2199     /**
2200      * Returns description of method result value
2201      *
2202      * @return external_description
2203      * @since 3.2
2204      */
2205     public static function message_processor_config_form_returns() {
2206         return null;
2207     }
2209     /**
2210      * Returns description of method parameters
2211      *
2212      * @return external_function_parameters
2213      * @since 3.2
2214      */
2215     public static function get_message_processor_parameters() {
2216         return new external_function_parameters(
2217             array(
2218                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'),
2219                 'name' => new external_value(PARAM_TEXT, 'The name of the message processor', VALUE_REQUIRED),
2220             )
2221         );
2222     }
2224     /**
2225      * Get a message processor.
2226      *
2227      * @param int $userid
2228      * @param string $name the name of the processor
2229      * @return external_description
2230      * @throws moodle_exception
2231      * @since 3.2
2232      */
2233     public static function get_message_processor($userid = 0, $name) {
2234         global $USER, $PAGE, $CFG;
2236         // Check if messaging is enabled.
2237         if (empty($CFG->messaging)) {
2238             throw new moodle_exception('disabled', 'message');
2239         }
2241         $params = self::validate_parameters(
2242             self::get_message_processor_parameters(),
2243             array(
2244                 'userid' => $userid,
2245                 'name' => $name,
2246             )
2247         );
2249         if (empty($params['userid'])) {
2250             $params['userid'] = $USER->id;
2251         }
2253         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
2254         core_user::require_active_user($user);
2255         self::validate_context(context_user::instance($params['userid']));
2257         $processor = get_message_processor($name);
2259         $processoroutput = new \core_message\output\processor($processor, $user);
2260         $renderer = $PAGE->get_renderer('core_message');
2262         return $processoroutput->export_for_template($renderer);
2263     }
2265     /**
2266      * Returns description of method result value
2267      *
2268      * @return external_description
2269      * @since 3.2
2270      */
2271     public static function get_message_processor_returns() {
2272         return new external_function_parameters(
2273             array(
2274                 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'),
2275                 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'),
2276             )
2277         );
2278     }
2280     /**
2281      * Check that the user has enough permission to retrieve message or notifications preferences.
2282      *
2283      * @param  int $userid the user id requesting the preferences
2284      * @return stdClass full user object
2285      * @throws moodle_exception
2286      * @since  Moodle 3.2
2287      */
2288     protected static function validate_preferences_permissions($userid) {
2289         global $USER;
2291         if (empty($userid)) {
2292             $user = $USER;
2293         } else {
2294             $user = core_user::get_user($userid, '*', MUST_EXIST);
2295             core_user::require_active_user($user);
2296         }
2298         $systemcontext = context_system::instance();
2299         self::validate_context($systemcontext);
2301         // Check access control.
2302         if ($user->id == $USER->id) {
2303             // Editing own message profile.
2304             require_capability('moodle/user:editownmessageprofile', $systemcontext);
2305         } else {
2306             // Teachers, parents, etc.
2307             $personalcontext = context_user::instance($user->id);
2308             require_capability('moodle/user:editmessageprofile', $personalcontext);
2309         }
2310         return $user;
2311     }
2313     /**
2314      * Returns a notification or message preference structure.
2315      *
2316      * @return external_single_structure the structure
2317      * @since  Moodle 3.2
2318      */
2319     protected static function get_preferences_structure() {
2320         return new external_single_structure(
2321             array(
2322                 'userid' => new external_value(PARAM_INT, 'User id'),
2323                 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'),
2324                 'processors' => new external_multiple_structure(
2325                     new external_single_structure(
2326                         array(
2327                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2328                             'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2329                             'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'),
2330                             'contextid' => new external_value(PARAM_INT, 'Context id'),
2331                             'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'),
2332                         )
2333                     ),
2334                     'Config form values'
2335                 ),
2336                 'components' => new external_multiple_structure(
2337                     new external_single_structure(
2338                         array(
2339                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2340                             'notifications' => new external_multiple_structure(
2341                                 new external_single_structure(
2342                                     array(
2343                                         'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2344                                         'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'),
2345                                         'processors' => new external_multiple_structure(
2346                                             new external_single_structure(
2347                                                 array(
2348                                                     'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2349                                                     'name' => new external_value(PARAM_PLUGIN, 'Processor name'),
2350                                                     'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'),
2351                                                     'userconfigured' => new external_value(PARAM_INT, 'Is configured?'),
2352                                                     'loggedin' => new external_single_structure(
2353                                                         array(
2354                                                             'name' => new external_value(PARAM_NOTAGS, 'Name'),
2355                                                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2356                                                             'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2357                                                         )
2358                                                     ),
2359                                                     'loggedoff' => new external_single_structure(
2360                                                         array(
2361                                                             'name' => new external_value(PARAM_NOTAGS, 'Name'),
2362                                                             'displayname' => new external_value(PARAM_TEXT, 'Display name'),
2363                                                             'checked' => new external_value(PARAM_BOOL, 'Is checked?'),
2364                                                         )
2365                                                     ),
2366                                                 )
2367                                             ),
2368                                             'Processors values for this notification'
2369                                         ),
2370                                     )
2371                                 ),
2372                                 'List of notificaitons for the component'
2373                             ),
2374                         )
2375                     ),
2376                     'Available components'
2377                 ),
2378             )
2379         );
2380     }
2382     /**
2383      * Returns description of method parameters
2384      *
2385      * @return external_function_parameters
2386      * @since 3.2
2387      */
2388     public static function get_user_notification_preferences_parameters() {
2389         return new external_function_parameters(
2390             array(
2391                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
2392             )
2393         );
2394     }
2396     /**
2397      * Get the notification preferences for a given user.
2398      *
2399      * @param int $userid id of the user, 0 for current user
2400      * @return external_description
2401      * @throws moodle_exception
2402      * @since 3.2
2403      */
2404     public static function get_user_notification_preferences($userid = 0) {
2405         global $PAGE;
2407         $params = self::validate_parameters(
2408             self::get_user_notification_preferences_parameters(),
2409             array(
2410                 'userid' => $userid,
2411             )
2412         );
2413         $user = self::validate_preferences_permissions($params['userid']);
2415         $processors = get_message_processors();
2416         $providers = message_get_providers_for_user($user->id);
2417         $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user);
2418         $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user);
2420         $renderer = $PAGE->get_renderer('core_message');
2422         $result = array(
2423             'warnings' => array(),
2424             'preferences' => $notificationlist->export_for_template($renderer)
2425         );
2426         return $result;
2427     }
2429     /**
2430      * Returns description of method result value
2431      *
2432      * @return external_description
2433      * @since 3.2
2434      */
2435     public static function get_user_notification_preferences_returns() {
2436         return new external_function_parameters(
2437             array(
2438                 'preferences' => self::get_preferences_structure(),
2439                 'warnings' => new external_warnings(),
2440             )
2441         );
2442     }
2445     /**
2446      * Returns description of method parameters
2447      *
2448      * @return external_function_parameters
2449      * @since 3.2
2450      */
2451     public static function get_user_message_preferences_parameters() {
2452         return new external_function_parameters(
2453             array(
2454                 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0)
2455             )
2456         );
2457     }
2459     /**
2460      * Get the notification preferences for a given user.
2461      *
2462      * @param int $userid id of the user, 0 for current user
2463      * @return external_description
2464      * @throws moodle_exception
2465      * @since 3.2
2466      */
2467     public static function get_user_message_preferences($userid = 0) {
2468         global $PAGE;
2470         $params = self::validate_parameters(
2471             self::get_user_message_preferences_parameters(),
2472             array(
2473                 'userid' => $userid,
2474             )
2475         );
2477         $user = self::validate_preferences_permissions($params['userid']);
2479         // Filter out enabled, available system_configured and user_configured processors only.
2480         $readyprocessors = array_filter(get_message_processors(), function($processor) {
2481             return $processor->enabled &&
2482                 $processor->configured &&
2483                 $processor->object->is_user_configured() &&
2484                 // Filter out processors that don't have and message preferences to configure.
2485                 $processor->object->has_message_preferences();
2486         });
2488         $providers = array_filter(message_get_providers_for_user($user->id), function($provider) {
2489             return $provider->component === 'moodle';
2490         });
2491         $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user);
2492         $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors,
2493             $providers, $preferences, $user);
2495         $renderer = $PAGE->get_renderer('core_message');
2497         $result = array(
2498             'warnings' => array(),
2499             'preferences' => $notificationlistoutput->export_for_template($renderer),
2500             'blocknoncontacts' => get_user_preferences('message_blocknoncontacts', '', $user->id) ? true : false,
2501         );
2502         return $result;
2503     }
2505     /**
2506      * Returns description of method result value
2507      *
2508      * @return external_description
2509      * @since 3.2
2510      */
2511     public static function get_user_message_preferences_returns() {
2512         return new external_function_parameters(
2513             array(
2514                 'preferences' => self::get_preferences_structure(),
2515                 'blocknoncontacts' => new external_value(PARAM_BOOL, 'Whether to block or not messages from non contacts'),
2516                 'warnings' => new external_warnings(),
2517             )
2518         );
2519     }