MDL-54687 core_message: added ability to send messages
[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
JM
54 'text' => new external_value(PARAM_RAW, 'the text of the message'),
55 'textformat' => new external_format_value('text', VALUE_DEFAULT),
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.
a623b6b8
JM
75 if (!$CFG->messaging) {
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'
201 )
202 )
203 );
204 }
205
206 /**
207 * Create contacts.
208 *
209 * @param array $userids array of user IDs.
210 * @return external_description
5bcfd504 211 * @since Moodle 2.5
d6731600
FM
212 */
213 public static function create_contacts($userids) {
436bbf89
DM
214 global $CFG;
215
216 // Check if messaging is enabled.
217 if (!$CFG->messaging) {
218 throw new moodle_exception('disabled', 'message');
219 }
220
d6731600
FM
221 $params = array('userids' => $userids);
222 $params = self::validate_parameters(self::create_contacts_parameters(), $params);
223
224 $warnings = array();
225 foreach ($params['userids'] as $id) {
226 if (!message_add_contact($id)) {
227 $warnings[] = array(
228 'item' => 'user',
229 'itemid' => $id,
230 'warningcode' => 'contactnotcreated',
231 'message' => 'The contact could not be created'
232 );
233 }
234 }
235 return $warnings;
236 }
237
238 /**
239 * Create contacts return description.
240 *
241 * @return external_description
5bcfd504 242 * @since Moodle 2.5
d6731600
FM
243 */
244 public static function create_contacts_returns() {
245 return new external_warnings();
246 }
247
248 /**
249 * Delete contacts parameters description.
250 *
251 * @return external_function_parameters
5bcfd504 252 * @since Moodle 2.5
d6731600
FM
253 */
254 public static function delete_contacts_parameters() {
255 return new external_function_parameters(
256 array(
257 'userids' => new external_multiple_structure(
258 new external_value(PARAM_INT, 'User ID'),
259 'List of user IDs'
260 )
261 )
262 );
263 }
264
265 /**
266 * Delete contacts.
267 *
268 * @param array $userids array of user IDs.
269 * @return null
5bcfd504 270 * @since Moodle 2.5
d6731600
FM
271 */
272 public static function delete_contacts($userids) {
436bbf89
DM
273 global $CFG;
274
275 // Check if messaging is enabled.
276 if (!$CFG->messaging) {
277 throw new moodle_exception('disabled', 'message');
278 }
279
d6731600
FM
280 $params = array('userids' => $userids);
281 $params = self::validate_parameters(self::delete_contacts_parameters(), $params);
282
283 foreach ($params['userids'] as $id) {
284 message_remove_contact($id);
285 }
286
287 return null;
288 }
289
290 /**
291 * Delete contacts return description.
292 *
293 * @return external_description
5bcfd504 294 * @since Moodle 2.5
d6731600
FM
295 */
296 public static function delete_contacts_returns() {
297 return null;
298 }
299
300 /**
301 * Block contacts parameters description.
302 *
303 * @return external_function_parameters
5bcfd504 304 * @since Moodle 2.5
d6731600
FM
305 */
306 public static function block_contacts_parameters() {
307 return new external_function_parameters(
308 array(
309 'userids' => new external_multiple_structure(
310 new external_value(PARAM_INT, 'User ID'),
311 'List of user IDs'
312 )
313 )
314 );
315 }
316
317 /**
318 * Block contacts.
319 *
320 * @param array $userids array of user IDs.
321 * @return external_description
5bcfd504 322 * @since Moodle 2.5
d6731600
FM
323 */
324 public static function block_contacts($userids) {
436bbf89
DM
325 global $CFG;
326
327 // Check if messaging is enabled.
328 if (!$CFG->messaging) {
329 throw new moodle_exception('disabled', 'message');
330 }
331
d6731600
FM
332 $params = array('userids' => $userids);
333 $params = self::validate_parameters(self::block_contacts_parameters(), $params);
334
335 $warnings = array();
336 foreach ($params['userids'] as $id) {
337 if (!message_block_contact($id)) {
338 $warnings[] = array(
339 'item' => 'user',
340 'itemid' => $id,
341 'warningcode' => 'contactnotblocked',
342 'message' => 'The contact could not be blocked'
343 );
344 }
345 }
346 return $warnings;
347 }
348
349 /**
350 * Block contacts return description.
351 *
352 * @return external_description
5bcfd504 353 * @since Moodle 2.5
d6731600
FM
354 */
355 public static function block_contacts_returns() {
356 return new external_warnings();
357 }
358
359 /**
360 * Unblock contacts parameters description.
361 *
362 * @return external_function_parameters
5bcfd504 363 * @since Moodle 2.5
d6731600
FM
364 */
365 public static function unblock_contacts_parameters() {
366 return new external_function_parameters(
367 array(
368 'userids' => new external_multiple_structure(
369 new external_value(PARAM_INT, 'User ID'),
370 'List of user IDs'
371 )
372 )
373 );
374 }
375
376 /**
377 * Unblock contacts.
378 *
379 * @param array $userids array of user IDs.
380 * @return null
5bcfd504 381 * @since Moodle 2.5
d6731600
FM
382 */
383 public static function unblock_contacts($userids) {
436bbf89
DM
384 global $CFG;
385
386 // Check if messaging is enabled.
387 if (!$CFG->messaging) {
388 throw new moodle_exception('disabled', 'message');
389 }
390
d6731600
FM
391 $params = array('userids' => $userids);
392 $params = self::validate_parameters(self::unblock_contacts_parameters(), $params);
393
394 foreach ($params['userids'] as $id) {
395 message_unblock_contact($id);
396 }
397
398 return null;
399 }
400
401 /**
402 * Unblock contacts return description.
403 *
404 * @return external_description
5bcfd504 405 * @since Moodle 2.5
d6731600
FM
406 */
407 public static function unblock_contacts_returns() {
408 return null;
409 }
410
9aa012b5
MN
411 /**
412 * Get messagearea conversations parameters.
413 *
414 * @return external_function_parameters
415 */
416 public static function data_for_messagearea_conversations_parameters() {
417 return new external_function_parameters(
418 array(
419 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
420 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
421 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
422 )
423 );
424 }
425
426 /**
427 * Get messagearea conversations.
428 *
429 * @param int $userid The id of the user who we are viewing conversations for
430 * @param int $limitfrom
431 * @param int $limitnum
432 * @return external_function_parameters
433 */
434 public static function data_for_messagearea_conversations($userid, $limitfrom = 0, $limitnum = 0) {
435 global $CFG, $PAGE;
436
437 // Check if messaging is enabled.
438 if (!$CFG->messaging) {
439 throw new moodle_exception('disabled', 'message');
440 }
441
442 $params = array(
443 'userid' => $userid,
444 'limitfrom' => $limitfrom,
445 'limitnum' => $limitnum
446 );
447 self::validate_parameters(self::data_for_messagearea_conversations_parameters(), $params);
448
449 self::validate_context(context_user::instance($userid));
450
451 $contacts = \core_message\api::get_conversations($userid, 0, $limitfrom, $limitnum);
452
453 $renderer = $PAGE->get_renderer('core_message');
454 return $contacts->export_for_template($renderer);
455 }
456
457 /**
458 * Get messagearea conversations returns.
459 *
460 * @return external_function_parameters
461 */
462 public static function data_for_messagearea_conversations_returns() {
463 return new external_function_parameters(
464 array(
465 'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
466 'conversationsselected' => new external_value(PARAM_BOOL, 'Determines if conversations were selected,
467 otherwise contacts were'),
468 'contacts' => new external_multiple_structure(
469 new external_single_structure(
470 array(
471 'userid' => new external_value(PARAM_INT, 'The user\'s id'),
472 'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
473 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
474 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
475 'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message', VALUE_OPTIONAL),
476 'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status', VALUE_OPTIONAL)
477 )
478 )
479 )
480 )
481 );
482 }
483
484 /**
485 * Get messagearea contacts parameters.
486 *
487 * @return external_function_parameters
488 */
489 public static function data_for_messagearea_contacts_parameters() {
490 return self::data_for_messagearea_conversations_parameters();
491 }
492
493 /**
494 * Get messagearea contacts parameters.
495 *
496 * @param int $userid The id of the user who we are viewing conversations for
497 * @param int $limitfrom
498 * @param int $limitnum
499 * @return external_function_parameters
500 */
501 public static function data_for_messagearea_contacts($userid, $limitfrom = 0, $limitnum = 0) {
502 global $CFG, $PAGE;
503
504 // Check if messaging is enabled.
505 if (!$CFG->messaging) {
506 throw new moodle_exception('disabled', 'message');
507 }
508
509 $params = array(
510 'userid' => $userid,
511 'limitfrom' => $limitfrom,
512 'limitnum' => $limitnum
513 );
514 self::validate_parameters(self::data_for_messagearea_contacts_parameters(), $params);
515
516 self::validate_context(context_user::instance($userid));
517
518 $contacts = \core_message\api::get_contacts($userid, $limitfrom, $limitnum);
519
520 $renderer = $PAGE->get_renderer('core_message');
521 return $contacts->export_for_template($renderer);
522 }
523
524 /**
525 * Get messagearea contacts returns.
526 *
527 * @return external_function_parameters
528 */
529 public static function data_for_messagearea_contacts_returns() {
530 return self::data_for_messagearea_conversations_returns();
531 }
532
3cd13828
MN
533 /**
534 * Get messagearea messages parameters.
535 *
536 * @return external_function_parameters
537 */
538 public static function data_for_messagearea_messages_parameters() {
539 return new external_function_parameters(
540 array(
541 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
542 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
543 'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
544 'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
545 )
546 );
547 }
548
549 /**
550 * Get messagearea messages.
551 *
552 * @param int $currentuserid The current user's id
553 * @param int $otheruserid The other user's id
554 * @param int $limitfrom
555 * @param int $limitnum
556 * @return external_description
557 */
558 public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0) {
559 global $CFG, $PAGE;
560
561 // Check if messaging is enabled.
562 if (!$CFG->messaging) {
563 throw new moodle_exception('disabled', 'message');
564 }
565
566 $params = array(
567 'currentuserid' => $currentuserid,
568 'otheruserid' => $otheruserid,
569 'limitfrom' => $limitfrom,
570 'limitnum' => $limitnum
571 );
572 self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
573
574 self::validate_context(context_user::instance($currentuserid));
575
576 $messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom, $limitnum);
577
578 $renderer = $PAGE->get_renderer('core_message');
579 return $messages->export_for_template($renderer);
580 }
581
582 /**
583 * Get messagearea messages returns.
584 *
585 * @return external_description
586 */
587 public static function data_for_messagearea_messages_returns() {
588 return new external_function_parameters(
589 array(
590 'iscurrentuser' => new external_value(PARAM_BOOL, 'Is the currently logged in user the user we are viewing the messages on behalf of?'),
591 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
592 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
593 'otheruserfullname' => new external_value(PARAM_NOTAGS, 'The other user\'s fullname'),
594 'messages' => new external_multiple_structure(
595 new external_single_structure(
596 array(
597 'text' => new external_value(PARAM_RAW, 'The text of the message'),
598 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
599 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
600 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
601 )
602 )
603 )
604 )
605 );
606 }
607
c060cd49
MN
608 /**
609 * Get the most recent message in a conversation parameters.
610 *
611 * @return external_function_parameters
612 */
613 public static function data_for_messagearea_get_most_recent_message_parameters() {
614 return new external_function_parameters(
615 array(
616 'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
617 'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
618 )
619 );
620 }
621
622 /**
623 * Get the most recent message in a conversation.
624 *
625 * @param int $currentuserid The current user's id
626 * @param int $otheruserid The other user's id
627 * @return external_single_structure
628 */
629 public static function data_for_messagearea_get_most_recent_message($currentuserid, $otheruserid) {
630 global $CFG, $PAGE;
631
632 // Check if messaging is enabled.
633 if (!$CFG->messaging) {
634 throw new moodle_exception('disabled', 'message');
635 }
636
637 $params = array(
638 'currentuserid' => $currentuserid,
639 'otheruserid' => $otheruserid
640 );
641 self::validate_parameters(self::data_for_messagearea_get_most_recent_message_parameters(), $params);
642
643 self::validate_context(context_user::instance($currentuserid));
644
645 $message = \core_message\api::get_most_recent_message($currentuserid, $otheruserid);
646
647 $renderer = $PAGE->get_renderer('core_message');
648 return $message->export_for_template($renderer);
649 }
650
651 /**
652 * Get messagearea get most recent message returns.
653 *
654 * @return external_single_structure
655 */
656 public static function data_for_messagearea_get_most_recent_message_returns() {
657 return new external_single_structure(
658 array(
659 'text' => new external_value(PARAM_RAW, 'The text of the message'),
660 'blocktime' => new external_value(PARAM_NOTAGS, 'The time to display above the message'),
661 'position' => new external_value(PARAM_ALPHA, 'The position of the text'),
662 'timesent' => new external_value(PARAM_NOTAGS, 'The time the message was sent'),
663 )
664 );
665 }
666
d6731600
FM
667 /**
668 * Get contacts parameters description.
669 *
670 * @return external_function_parameters
5bcfd504 671 * @since Moodle 2.5
d6731600
FM
672 */
673 public static function get_contacts_parameters() {
674 return new external_function_parameters(array());
675 }
676
677 /**
678 * Get contacts.
679 *
680 * @param array $userids array of user IDs.
681 * @return external_description
5bcfd504 682 * @since Moodle 2.5
d6731600
FM
683 */
684 public static function get_contacts() {
d85bedf7 685 global $CFG, $PAGE;
436bbf89
DM
686
687 // Check if messaging is enabled.
688 if (!$CFG->messaging) {
689 throw new moodle_exception('disabled', 'message');
690 }
691
d6731600
FM
692 require_once($CFG->dirroot . '/user/lib.php');
693
694 list($online, $offline, $strangers) = message_get_contacts();
695 $allcontacts = array('online' => $online, 'offline' => $offline, 'strangers' => $strangers);
696 foreach ($allcontacts as $mode => $contacts) {
697 foreach ($contacts as $key => $contact) {
698 $newcontact = array(
699 'id' => $contact->id,
700 'fullname' => fullname($contact),
701 'unread' => $contact->messagecount
702 );
703
d85bedf7
JL
704 $userpicture = new user_picture($contact);
705 $userpicture->size = 1; // Size f1.
706 $newcontact['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
707 $userpicture->size = 0; // Size f2.
708 $newcontact['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
d6731600
FM
709
710 $allcontacts[$mode][$key] = $newcontact;
711 }
712 }
713 return $allcontacts;
714 }
715
716 /**
717 * Get contacts return description.
718 *
719 * @return external_description
5bcfd504 720 * @since Moodle 2.5
d6731600
FM
721 */
722 public static function get_contacts_returns() {
723 return new external_single_structure(
724 array(
725 'online' => new external_multiple_structure(
726 new external_single_structure(
727 array(
728 'id' => new external_value(PARAM_INT, 'User ID'),
729 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
730 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
731 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
732 'unread' => new external_value(PARAM_INT, 'Unread message count')
733 )
734 ),
735 'List of online contacts'
736 ),
737 'offline' => new external_multiple_structure(
738 new external_single_structure(
739 array(
740 'id' => new external_value(PARAM_INT, 'User ID'),
741 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
742 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
743 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
744 'unread' => new external_value(PARAM_INT, 'Unread message count')
745 )
746 ),
747 'List of offline contacts'
748 ),
749 'strangers' => new external_multiple_structure(
750 new external_single_structure(
751 array(
752 'id' => new external_value(PARAM_INT, 'User ID'),
753 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
754 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
755 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL),
756 'unread' => new external_value(PARAM_INT, 'Unread message count')
757 )
758 ),
759 'List of users that are not in the user\'s contact list but have sent a message'
760 )
761 )
762 );
763 }
764
765 /**
766 * Search contacts parameters description.
767 *
768 * @return external_function_parameters
5bcfd504 769 * @since Moodle 2.5
d6731600
FM
770 */
771 public static function search_contacts_parameters() {
772 return new external_function_parameters(
773 array(
774 'searchtext' => new external_value(PARAM_CLEAN, 'String the user\'s fullname has to match to be found'),
775 'onlymycourses' => new external_value(PARAM_BOOL, 'Limit search to the user\'s courses',
776 VALUE_DEFAULT, false)
777 )
778 );
779 }
780
781 /**
782 * Search contacts.
783 *
784 * @param string $searchtext query string.
785 * @param bool $onlymycourses limit the search to the user's courses only.
786 * @return external_description
5bcfd504 787 * @since Moodle 2.5
d6731600
FM
788 */
789 public static function search_contacts($searchtext, $onlymycourses = false) {
d85bedf7 790 global $CFG, $USER, $PAGE;
11d83ab3 791 require_once($CFG->dirroot . '/user/lib.php');
436bbf89
DM
792
793 // Check if messaging is enabled.
794 if (!$CFG->messaging) {
795 throw new moodle_exception('disabled', 'message');
796 }
797
d6731600
FM
798 require_once($CFG->libdir . '/enrollib.php');
799
800 $params = array('searchtext' => $searchtext, 'onlymycourses' => $onlymycourses);
801 $params = self::validate_parameters(self::search_contacts_parameters(), $params);
802
803 // Extra validation, we do not allow empty queries.
804 if ($params['searchtext'] === '') {
805 throw new moodle_exception('querystringcannotbeempty');
806 }
807
808 $courseids = array();
809 if ($params['onlymycourses']) {
810 $mycourses = enrol_get_my_courses(array('id'));
811 foreach ($mycourses as $mycourse) {
812 $courseids[] = $mycourse->id;
813 }
814 } else {
815 $courseids[] = SITEID;
816 }
817
818 // Retrieving the users matching the query.
819 $users = message_search_users($courseids, $params['searchtext']);
820 $results = array();
821 foreach ($users as $user) {
822 $results[$user->id] = $user;
823 }
824
825 // Reorganising information.
826 foreach ($results as &$user) {
827 $newuser = array(
828 'id' => $user->id,
829 'fullname' => fullname($user)
830 );
831
832 // Avoid undefined property notice as phone not specified.
833 $user->phone1 = null;
834 $user->phone2 = null;
835
d85bedf7
JL
836 $userpicture = new user_picture($user);
837 $userpicture->size = 1; // Size f1.
838 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
839 $userpicture->size = 0; // Size f2.
840 $newuser['profileimageurlsmall'] = $userpicture->get_url($PAGE)->out(false);
d6731600
FM
841
842 $user = $newuser;
843 }
844
845 return $results;
846 }
847
848 /**
849 * Search contacts return description.
850 *
851 * @return external_description
5bcfd504 852 * @since Moodle 2.5
d6731600
FM
853 */
854 public static function search_contacts_returns() {
855 return new external_multiple_structure(
856 new external_single_structure(
857 array(
858 'id' => new external_value(PARAM_INT, 'User ID'),
859 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
860 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL),
861 'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL', VALUE_OPTIONAL)
862 )
863 ),
864 'List of contacts'
865 );
866 }
aff9da17
JL
867
868 /**
869 * Get messages parameters description.
870 *
871 * @return external_function_parameters
193edf7f 872 * @since 2.8
aff9da17
JL
873 */
874 public static function get_messages_parameters() {
875 return new external_function_parameters(
876 array(
6ff4464b 877 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED),
127ef540
SH
878 'useridfrom' => new external_value(
879 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user',
880 VALUE_DEFAULT, 0),
881 'type' => new external_value(
882 PARAM_ALPHA, 'type of message to return, expected values are: notifications, conversations and both',
883 VALUE_DEFAULT, 'both'),
6ff4464b 884 'read' => new external_value(PARAM_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true),
127ef540
SH
885 'newestfirst' => new external_value(
886 PARAM_BOOL, 'true for ordering by newest first, false for oldest first',
887 VALUE_DEFAULT, true),
aff9da17 888 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0),
127ef540
SH
889 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0)
890 )
aff9da17
JL
891 );
892 }
893
894 /**
895 * Get messages function implementation.
127ef540
SH
896 *
897 * @since 2.8
898 * @throws invalid_parameter_exception
899 * @throws moodle_exception
6ff4464b
JL
900 * @param int $useridto the user id who received the message
901 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user
193edf7f 902 * @param string $type type of message to return, expected values: notifications, conversations and both
aff9da17 903 * @param bool $read true for retreiving read messages, false for unread
6ff4464b 904 * @param bool $newestfirst true for ordering by newest first, false for oldest first
aff9da17
JL
905 * @param int $limitfrom limit from
906 * @param int $limitnum limit num
907 * @return external_description
aff9da17 908 */
193edf7f 909 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true,
aff9da17 910 $newestfirst = true, $limitfrom = 0, $limitnum = 0) {
127ef540 911 global $CFG, $USER;
aff9da17
JL
912
913 $warnings = array();
914
915 $params = array(
916 'useridto' => $useridto,
6ff4464b 917 'useridfrom' => $useridfrom,
aff9da17
JL
918 'type' => $type,
919 'read' => $read,
aff9da17
JL
920 'newestfirst' => $newestfirst,
921 'limitfrom' => $limitfrom,
922 'limitnum' => $limitnum
923 );
924
925 $params = self::validate_parameters(self::get_messages_parameters(), $params);
926
927 $context = context_system::instance();
928 self::validate_context($context);
929
930 $useridto = $params['useridto'];
6ff4464b 931 $useridfrom = $params['useridfrom'];
aff9da17
JL
932 $type = $params['type'];
933 $read = $params['read'];
aff9da17
JL
934 $newestfirst = $params['newestfirst'];
935 $limitfrom = $params['limitfrom'];
936 $limitnum = $params['limitnum'];
937
938 $allowedvalues = array('notifications', 'conversations', 'both');
939 if (!in_array($type, $allowedvalues)) {
940 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' .
941 'allowed values are: ' . implode(',', $allowedvalues));
942 }
943
944 // Check if private messaging between users is allowed.
945 if (empty($CFG->messaging)) {
946 // If we are retreiving only conversations, and messaging is disabled, throw an exception.
aff9da17
JL
947 if ($type == "conversations") {
948 throw new moodle_exception('disabled', 'message');
949 }
950 if ($type == "both") {
951 $warning = array();
952 $warning['item'] = 'message';
953 $warning['itemid'] = $USER->id;
954 $warning['warningcode'] = '1';
955 $warning['message'] = 'Private messages (conversations) are not enabled in this site.
956 Only notifications will be returned';
957 $warnings[] = $warning;
958 }
959 }
960
961 if (!empty($useridto)) {
6ff4464b
JL
962 if (core_user::is_real_user($useridto)) {
963 $userto = core_user::get_user($useridto, '*', MUST_EXIST);
964 } else {
965 throw new moodle_exception('invaliduser');
966 }
aff9da17
JL
967 }
968
969 if (!empty($useridfrom)) {
970 // We use get_user here because the from user can be the noreply or support user.
971 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST);
972 }
973
974 // Check if the current user is the sender/receiver or just a privileged user.
975 if ($useridto != $USER->id and $useridfrom != $USER->id and
976 !has_capability('moodle/site:readallmessages', $context)) {
977 throw new moodle_exception('accessdenied', 'admin');
978 }
979
127ef540 980 // Which type of messages to retrieve.
193edf7f 981 $notifications = -1;
aff9da17 982 if ($type != 'both') {
193edf7f 983 $notifications = ($type == 'notifications') ? 1 : 0;
aff9da17
JL
984 }
985
aff9da17 986 $orderdirection = $newestfirst ? 'DESC' : 'ASC';
193edf7f 987 $sort = "mr.timecreated $orderdirection";
aff9da17 988
193edf7f 989 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) {
aff9da17
JL
990 $canviewfullname = has_capability('moodle/site:viewfullnames', $context);
991
992 // In some cases, we don't need to get the to/from user objects from the sql query.
993 $userfromfullname = '';
994 $usertofullname = '';
995
996 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there.
997 if (!empty($useridto)) {
998 $usertofullname = fullname($userto, $canviewfullname);
999 // The user from may or may not be filled.
1000 if (!empty($useridfrom)) {
1001 $userfromfullname = fullname($userfrom, $canviewfullname);
1002 }
1003 } else {
1004 // If the useridto field is empty, the useridfrom must be filled.
1005 $userfromfullname = fullname($userfrom, $canviewfullname);
1006 }
aff9da17
JL
1007 foreach ($messages as $mid => $message) {
1008
ea21d637
JL
1009 // Do not return deleted messages.
1010 if (($useridto == $USER->id and $message->timeusertodeleted) or
1011 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) {
1012
1013 unset($messages[$mid]);
1014 continue;
1015 }
1016
aff9da17
JL
1017 // We need to get the user from the query.
1018 if (empty($userfromfullname)) {
6ff4464b
JL
1019 // Check for non-reply and support users.
1020 if (core_user::is_real_user($message->useridfrom)) {
127ef540 1021 $user = new stdClass();
6ff4464b
JL
1022 $user = username_load_fields_from_object($user, $message, 'userfrom');
1023 $message->userfromfullname = fullname($user, $canviewfullname);
1024 } else {
1025 $user = core_user::get_user($message->useridfrom);
1026 $message->userfromfullname = fullname($user, $canviewfullname);
1027 }
aff9da17
JL
1028 } else {
1029 $message->userfromfullname = $userfromfullname;
1030 }
1031
1032 // We need to get the user from the query.
1033 if (empty($usertofullname)) {
127ef540 1034 $user = new stdClass();
aff9da17
JL
1035 $user = username_load_fields_from_object($user, $message, 'userto');
1036 $message->usertofullname = fullname($user, $canviewfullname);
1037 } else {
1038 $message->usertofullname = $usertofullname;
1039 }
1040
193edf7f 1041 // This field is only available in the message_read table.
aff9da17
JL
1042 if (!isset($message->timeread)) {
1043 $message->timeread = 0;
1044 }
1045
aff9da17 1046 $message->text = message_format_message_text($message);
aff9da17
JL
1047 $messages[$mid] = (array) $message;
1048 }
1049 }
1050
1051 $results = array(
1052 'messages' => $messages,
1053 'warnings' => $warnings
1054 );
1055
1056 return $results;
1057 }
1058
1059 /**
1060 * Get messages return description.
1061 *
6ff4464b 1062 * @return external_single_structure
193edf7f 1063 * @since 2.8
aff9da17
JL
1064 */
1065 public static function get_messages_returns() {
1066 return new external_single_structure(
1067 array(
1068 'messages' => new external_multiple_structure(
1069 new external_single_structure(
1070 array(
193edf7f 1071 'id' => new external_value(PARAM_INT, 'Message id'),
aff9da17
JL
1072 'useridfrom' => new external_value(PARAM_INT, 'User from id'),
1073 'useridto' => new external_value(PARAM_INT, 'User to id'),
1074 'subject' => new external_value(PARAM_TEXT, 'The message subject'),
1075 'text' => new external_value(PARAM_RAW, 'The message text formated'),
1076 'fullmessage' => new external_value(PARAM_RAW, 'The message'),
193edf7f 1077 'fullmessageformat' => new external_format_value('fullmessage'),
aff9da17
JL
1078 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'),
1079 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'),
1080 'notification' => new external_value(PARAM_INT, 'Is a notification?'),
1081 'contexturl' => new external_value(PARAM_RAW, 'Context URL'),
1082 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'),
1083 'timecreated' => new external_value(PARAM_INT, 'Time created'),
1084 'timeread' => new external_value(PARAM_INT, 'Time read'),
1085 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
1086 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
1087 ), 'message'
1088 )
1089 ),
1090 'warnings' => new external_warnings()
1091 )
1092 );
1093 }
1094
60ab2e1b
JL
1095 /**
1096 * Get blocked users parameters description.
1097 *
1098 * @return external_function_parameters
1099 * @since 2.9
1100 */
1101 public static function get_blocked_users_parameters() {
1102 return new external_function_parameters(
1103 array(
1104 'userid' => new external_value(PARAM_INT,
1105 'the user whose blocked users we want to retrieve',
1106 VALUE_REQUIRED),
1107 )
1108 );
1109 }
1110
1111 /**
1112 * Retrieve a list of users blocked
1113 *
1114 * @param int $userid the user whose blocked users we want to retrieve
1115 * @return external_description
1116 * @since 2.9
1117 */
1118 public static function get_blocked_users($userid) {
d85bedf7 1119 global $CFG, $USER, $PAGE;
60ab2e1b
JL
1120
1121 // Warnings array, it can be empty at the end but is mandatory.
1122 $warnings = array();
1123
1124 // Validate params.
1125 $params = array(
1126 'userid' => $userid
1127 );
1128 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params);
1129 $userid = $params['userid'];
1130
1131 // Validate context.
1132 $context = context_system::instance();
1133 self::validate_context($context);
1134
1135 // Check if private messaging between users is allowed.
1136 if (empty($CFG->messaging)) {
1137 throw new moodle_exception('disabled', 'message');
1138 }
1139
4485f7c5
JL
1140 $user = core_user::get_user($userid, '*', MUST_EXIST);
1141 core_user::require_active_user($user);
60ab2e1b
JL
1142
1143 // Check if we have permissions for retrieve the information.
1144 if ($userid != $USER->id and !has_capability('moodle/site:readallmessages', $context)) {
1145 throw new moodle_exception('accessdenied', 'admin');
1146 }
1147
1148 // Now, we can get safely all the blocked users.
1149 $users = message_get_blocked_users($user);
1150
1151 $blockedusers = array();
1152 foreach ($users as $user) {
1153 $newuser = array(
1154 'id' => $user->id,
1155 'fullname' => fullname($user),
1156 );
0b074e88 1157
d85bedf7
JL
1158 $userpicture = new user_picture($user);
1159 $userpicture->size = 1; // Size f1.
1160 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false);
60ab2e1b
JL
1161
1162 $blockedusers[] = $newuser;
1163 }
1164
1165 $results = array(
1166 'users' => $blockedusers,
1167 'warnings' => $warnings
1168 );
1169 return $results;
1170 }
1171
1172 /**
1173 * Get blocked users return description.
1174 *
1175 * @return external_single_structure
1176 * @since 2.9
1177 */
1178 public static function get_blocked_users_returns() {
1179 return new external_single_structure(
1180 array(
1181 'users' => new external_multiple_structure(
1182 new external_single_structure(
1183 array(
1184 'id' => new external_value(PARAM_INT, 'User ID'),
1185 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'),
1186 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL)
1187 )
1188 ),
1189 'List of blocked users'
1190 ),
1191 'warnings' => new external_warnings()
1192 )
1193 );
1194 }
1195
31c474da
JL
1196 /**
1197 * Returns description of method parameters
1198 *
1199 * @return external_function_parameters
1200 * @since 2.9
1201 */
1202 public static function mark_message_read_parameters() {
1203 return new external_function_parameters(
1204 array(
1205 'messageid' => new external_value(PARAM_INT, 'id of the message (in the message table)'),
1206 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read')
1207 )
1208 );
1209 }
1210
1211 /**
1212 * Mark a single message as read, trigger message_viewed event
1213 *
1214 * @param int $messageid id of the message (in the message table)
1215 * @param int $timeread timestamp for when the message should be marked read
1216 * @return external_description
1217 * @throws invalid_parameter_exception
1218 * @throws moodle_exception
1219 * @since 2.9
1220 */
1221 public static function mark_message_read($messageid, $timeread) {
1222 global $CFG, $DB, $USER;
31c474da
JL
1223
1224 // Check if private messaging between users is allowed.
1225 if (empty($CFG->messaging)) {
1226 throw new moodle_exception('disabled', 'message');
1227 }
1228
1229 // Warnings array, it can be empty at the end but is mandatory.
1230 $warnings = array();
1231
1232 // Validate params.
1233 $params = array(
1234 'messageid' => $messageid,
1235 'timeread' => $timeread
1236 );
1237 $params = self::validate_parameters(self::mark_message_read_parameters(), $params);
1238
1239 // Validate context.
1240 $context = context_system::instance();
1241 self::validate_context($context);
1242
1243 $message = $DB->get_record('message', array('id' => $params['messageid']), '*', MUST_EXIST);
1244
1245 if ($message->useridto != $USER->id) {
1246 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read');
1247 }
1248
1249 $messageid = message_mark_message_read($message, $params['timeread']);
1250
1251 $results = array(
1252 'messageid' => $messageid,
1253 'warnings' => $warnings
1254 );
1255 return $results;
1256 }
1257
1258 /**
1259 * Returns description of method result value
1260 *
1261 * @return external_description
1262 * @since 2.9
1263 */
1264 public static function mark_message_read_returns() {
1265 return new external_single_structure(
1266 array(
1267 'messageid' => new external_value(PARAM_INT, 'the id of the message in the message_read table'),
1268 'warnings' => new external_warnings()
1269 )
1270 );
1271 }
1272
419b1128
JL
1273 /**
1274 * Returns description of method parameters
1275 *
1276 * @return external_function_parameters
1277 * @since 3.1
1278 */
1279 public static function delete_message_parameters() {
1280 return new external_function_parameters(
1281 array(
1282 'messageid' => new external_value(PARAM_INT, 'The message id'),
1283 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'),
1284 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true)
1285 )
1286 );
1287 }
1288
1289 /**
1290 * Deletes a message
1291 *
1292 * @param int $messageid the message id
1293 * @param int $userid the user id of who we want to delete the message for
1294 * @param bool $read if is a message read (default to true)
1295 * @return external_description
1296 * @throws moodle_exception
1297 * @since 3.1
1298 */
1299 public static function delete_message($messageid, $userid, $read = true) {
1300 global $CFG, $DB;
419b1128
JL
1301
1302 // Check if private messaging between users is allowed.
1303 if (empty($CFG->messaging)) {
1304 throw new moodle_exception('disabled', 'message');
1305 }
1306
1307 // Warnings array, it can be empty at the end but is mandatory.
1308 $warnings = array();
1309
1310 // Validate params.
1311 $params = array(
1312 'messageid' => $messageid,
1313 'userid' => $userid,
1314 'read' => $read
1315 );
1316 $params = self::validate_parameters(self::delete_message_parameters(), $params);
1317
1318 // Validate context.
1319 $context = context_system::instance();
1320 self::validate_context($context);
1321
1322 $messagestable = $params['read'] ? 'message_read' : 'message';
1323 $message = $DB->get_record($messagestable, array('id' => $params['messageid']), '*', MUST_EXIST);
1324
1325 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
1326 core_user::require_active_user($user);
1327
1328 $status = false;
1329 if (message_can_delete_message($message, $user->id)) {
1330 $status = message_delete_message($message, $user->id);;
1331 } else {
1332 throw new moodle_exception('You do not have permission to delete this message');
1333 }
1334
1335 $results = array(
1336 'status' => $status,
1337 'warnings' => $warnings
1338 );
1339 return $results;
1340 }
1341
1342 /**
1343 * Returns description of method result value
1344 *
1345 * @return external_description
1346 * @since 3.1
1347 */
1348 public static function delete_message_returns() {
1349 return new external_single_structure(
1350 array(
1351 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'),
1352 'warnings' => new external_warnings()
1353 )
1354 );
1355 }
1356
a623b6b8 1357}