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