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