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