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