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