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