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