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