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