Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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_BOOL, 'true for getting read messages, false for unread', VALUE_DEFAULT, true), 1967 'newestfirst' => new external_value( 1968 PARAM_BOOL, 'true for ordering by newest first, false for oldest first', 1969 VALUE_DEFAULT, true), 1970 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0), 1971 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0) 1972 ) 1973 ); 1974 } 1975 1976 /** 1977 * Get messages function implementation. 1978 * 1979 * @since 2.8 1980 * @throws invalid_parameter_exception 1981 * @throws moodle_exception 1982 * @param int $useridto the user id who received the message 1983 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user 1984 * @param string $type type of message to return, expected values: notifications, conversations and both 1985 * @param bool $read true for retreiving read messages, false for unread 1986 * @param bool $newestfirst true for ordering by newest first, false for oldest first 1987 * @param int $limitfrom limit from 1988 * @param int $limitnum limit num 1989 * @return external_description 1990 */ 1991 public static function get_messages($useridto, $useridfrom = 0, $type = 'both', $read = true, 1992 $newestfirst = true, $limitfrom = 0, $limitnum = 0) { 1993 global $CFG, $USER; 1994 1995 $warnings = array(); 1996 1997 $params = array( 1998 'useridto' => $useridto, 1999 'useridfrom' => $useridfrom, 2000 'type' => $type, 2001 'read' => $read, 2002 'newestfirst' => $newestfirst, 2003 'limitfrom' => $limitfrom, 2004 'limitnum' => $limitnum 2005 ); 2006 2007 $params = self::validate_parameters(self::get_messages_parameters(), $params); 2008 2009 $context = context_system::instance(); 2010 self::validate_context($context); 2011 2012 $useridto = $params['useridto']; 2013 $useridfrom = $params['useridfrom']; 2014 $type = $params['type']; 2015 $read = $params['read']; 2016 $newestfirst = $params['newestfirst']; 2017 $limitfrom = $params['limitfrom']; 2018 $limitnum = $params['limitnum']; 2019 2020 $allowedvalues = array('notifications', 'conversations', 'both'); 2021 if (!in_array($type, $allowedvalues)) { 2022 throw new invalid_parameter_exception('Invalid value for type parameter (value: ' . $type . '),' . 2023 'allowed values are: ' . implode(',', $allowedvalues)); 2024 } 2025 2026 // Check if private messaging between users is allowed. 2027 if (empty($CFG->messaging)) { 2028 // If we are retreiving only conversations, and messaging is disabled, throw an exception. 2029 if ($type == "conversations") { 2030 throw new moodle_exception('disabled', 'message'); 2031 } 2032 if ($type == "both") { 2033 $warning = array(); 2034 $warning['item'] = 'message'; 2035 $warning['itemid'] = $USER->id; 2036 $warning['warningcode'] = '1'; 2037 $warning['message'] = 'Private messages (conversations) are not enabled in this site. 2038 Only notifications will be returned'; 2039 $warnings[] = $warning; 2040 } 2041 } 2042 2043 if (!empty($useridto)) { 2044 if (core_user::is_real_user($useridto)) { 2045 $userto = core_user::get_user($useridto, '*', MUST_EXIST); 2046 } else { 2047 throw new moodle_exception('invaliduser'); 2048 } 2049 } 2050 2051 if (!empty($useridfrom)) { 2052 // We use get_user here because the from user can be the noreply or support user. 2053 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST); 2054 } 2055 2056 // Check if the current user is the sender/receiver or just a privileged user. 2057 if ($useridto != $USER->id and $useridfrom != $USER->id and 2058 !has_capability('moodle/site:readallmessages', $context)) { 2059 throw new moodle_exception('accessdenied', 'admin'); 2060 } 2061 2062 // Which type of messages to retrieve. 2063 $notifications = -1; 2064 if ($type != 'both') { 2065 $notifications = ($type == 'notifications') ? 1 : 0; 2066 } 2067 2068 $orderdirection = $newestfirst ? 'DESC' : 'ASC'; 2069 $sort = "mr.timecreated $orderdirection"; 2070 2071 if ($messages = message_get_messages($useridto, $useridfrom, $notifications, $read, $sort, $limitfrom, $limitnum)) { 2072 $canviewfullname = has_capability('moodle/site:viewfullnames', $context); 2073 2074 // In some cases, we don't need to get the to/from user objects from the sql query. 2075 $userfromfullname = ''; 2076 $usertofullname = ''; 2077 2078 // In this case, the useridto field is not empty, so we can get the user destinatary fullname from there. 2079 if (!empty($useridto)) { 2080 $usertofullname = fullname($userto, $canviewfullname); 2081 // The user from may or may not be filled. 2082 if (!empty($useridfrom)) { 2083 $userfromfullname = fullname($userfrom, $canviewfullname); 2084 } 2085 } else { 2086 // If the useridto field is empty, the useridfrom must be filled. 2087 $userfromfullname = fullname($userfrom, $canviewfullname); 2088 } 2089 foreach ($messages as $mid => $message) { 2090 2091 // Do not return deleted messages. 2092 if (!$message->notification) { 2093 if (($useridto == $USER->id and $message->timeusertodeleted) or 2094 ($useridfrom == $USER->id and $message->timeuserfromdeleted)) { 2095 unset($messages[$mid]); 2096 continue; 2097 } 2098 } 2099 2100 // We need to get the user from the query. 2101 if (empty($userfromfullname)) { 2102 // Check for non-reply and support users. 2103 if (core_user::is_real_user($message->useridfrom)) { 2104 $user = new stdClass(); 2105 $user = username_load_fields_from_object($user, $message, 'userfrom'); 2106 $message->userfromfullname = fullname($user, $canviewfullname); 2107 } else { 2108 $user = core_user::get_user($message->useridfrom); 2109 $message->userfromfullname = fullname($user, $canviewfullname); 2110 } 2111 } else { 2112 $message->userfromfullname = $userfromfullname; 2113 } 2114 2115 // We need to get the user from the query. 2116 if (empty($usertofullname)) { 2117 $user = new stdClass(); 2118 $user = username_load_fields_from_object($user, $message, 'userto'); 2119 $message->usertofullname = fullname($user, $canviewfullname); 2120 } else { 2121 $message->usertofullname = $usertofullname; 2122 } 2123 2124 $message->text = message_format_message_text($message); 2125 $messages[$mid] = (array) $message; 2126 } 2127 } 2128 2129 $results = array( 2130 'messages' => $messages, 2131 'warnings' => $warnings 2132 ); 2133 2134 return $results; 2135 } 2136 2137 /** 2138 * Get messages return description. 2139 * 2140 * @return external_single_structure 2141 * @since 2.8 2142 */ 2143 public static function get_messages_returns() { 2144 return new external_single_structure( 2145 array( 2146 'messages' => new external_multiple_structure( 2147 new external_single_structure( 2148 array( 2149 'id' => new external_value(PARAM_INT, 'Message id'), 2150 'useridfrom' => new external_value(PARAM_INT, 'User from id'), 2151 'useridto' => new external_value(PARAM_INT, 'User to id'), 2152 'subject' => new external_value(PARAM_TEXT, 'The message subject'), 2153 'text' => new external_value(PARAM_RAW, 'The message text formated'), 2154 'fullmessage' => new external_value(PARAM_RAW, 'The message'), 2155 'fullmessageformat' => new external_format_value('fullmessage'), 2156 'fullmessagehtml' => new external_value(PARAM_RAW, 'The message in html'), 2157 'smallmessage' => new external_value(PARAM_RAW, 'The shorten message'), 2158 'notification' => new external_value(PARAM_INT, 'Is a notification?'), 2159 'contexturl' => new external_value(PARAM_RAW, 'Context URL'), 2160 'contexturlname' => new external_value(PARAM_TEXT, 'Context URL link name'), 2161 'timecreated' => new external_value(PARAM_INT, 'Time created'), 2162 'timeread' => new external_value(PARAM_INT, 'Time read'), 2163 'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'), 2164 'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name'), 2165 'component' => new external_value(PARAM_TEXT, 'The component that generated the notification', 2166 VALUE_OPTIONAL), 2167 'eventtype' => new external_value(PARAM_TEXT, 'The type of notification', VALUE_OPTIONAL), 2168 'customdata' => new external_value(PARAM_RAW, 'Custom data to be passed to the message processor. 2169 The data here is serialised using json_encode().', VALUE_OPTIONAL), 2170 ), 'message' 2171 ) 2172 ), 2173 'warnings' => new external_warnings() 2174 ) 2175 ); 2176 } 2177 2178 /** 2179 * Mark all notifications as read parameters description. 2180 * 2181 * @return external_function_parameters 2182 * @since 3.2 2183 */ 2184 public static function mark_all_notifications_as_read_parameters() { 2185 return new external_function_parameters( 2186 array( 2187 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED), 2188 'useridfrom' => new external_value( 2189 PARAM_INT, 'the user id who send the message, 0 for any user. -10 or -20 for no-reply or support user', 2190 VALUE_DEFAULT, 0), 2191 'timecreatedto' => new external_value( 2192 PARAM_INT, 'mark messages created before this time as read, 0 for all messages', 2193 VALUE_DEFAULT, 0), 2194 ) 2195 ); 2196 } 2197 2198 /** 2199 * Mark all notifications as read function. 2200 * 2201 * @since 3.2 2202 * @throws invalid_parameter_exception 2203 * @throws moodle_exception 2204 * @param int $useridto the user id who received the message 2205 * @param int $useridfrom the user id who send the message. -10 or -20 for no-reply or support user 2206 * @param int $timecreatedto mark message created before this time as read, 0 for all messages 2207 * @return external_description 2208 */ 2209 public static function mark_all_notifications_as_read($useridto, $useridfrom, $timecreatedto = 0) { 2210 global $USER; 2211 2212 $params = self::validate_parameters( 2213 self::mark_all_notifications_as_read_parameters(), 2214 array( 2215 'useridto' => $useridto, 2216 'useridfrom' => $useridfrom, 2217 'timecreatedto' => $timecreatedto, 2218 ) 2219 ); 2220 2221 $context = context_system::instance(); 2222 self::validate_context($context); 2223 2224 $useridto = $params['useridto']; 2225 $useridfrom = $params['useridfrom']; 2226 $timecreatedto = $params['timecreatedto']; 2227 2228 if (!empty($useridto)) { 2229 if (core_user::is_real_user($useridto)) { 2230 $userto = core_user::get_user($useridto, '*', MUST_EXIST); 2231 } else { 2232 throw new moodle_exception('invaliduser'); 2233 } 2234 } 2235 2236 if (!empty($useridfrom)) { 2237 // We use get_user here because the from user can be the noreply or support user. 2238 $userfrom = core_user::get_user($useridfrom, '*', MUST_EXIST); 2239 } 2240 2241 // Check if the current user is the sender/receiver or just a privileged user. 2242 if ($useridto != $USER->id and $useridfrom != $USER->id and 2243 // The deleteanymessage cap seems more reasonable here than readallmessages. 2244 !has_capability('moodle/site:deleteanymessage', $context)) { 2245 throw new moodle_exception('accessdenied', 'admin'); 2246 } 2247 2248 \core_message\api::mark_all_notifications_as_read($useridto, $useridfrom, $timecreatedto); 2249 2250 return true; 2251 } 2252 2253 /** 2254 * Mark all notifications as read return description. 2255 * 2256 * @return external_single_structure 2257 * @since 3.2 2258 */ 2259 public static function mark_all_notifications_as_read_returns() { 2260 return new external_value(PARAM_BOOL, 'True if the messages were marked read, false otherwise'); 2261 } 2262 2263 /** 2264 * Get unread conversations count parameters description. 2265 * 2266 * @return external_function_parameters 2267 * @since 3.2 2268 */ 2269 public static function get_unread_conversations_count_parameters() { 2270 return new external_function_parameters( 2271 array( 2272 'useridto' => new external_value(PARAM_INT, 'the user id who received the message, 0 for any user', VALUE_REQUIRED), 2273 ) 2274 ); 2275 } 2276 2277 /** 2278 * Get unread messages count function. 2279 * 2280 * @since 3.2 2281 * @throws invalid_parameter_exception 2282 * @throws moodle_exception 2283 * @param int $useridto the user id who received the message 2284 * @return external_description 2285 */ 2286 public static function get_unread_conversations_count($useridto) { 2287 global $USER, $CFG; 2288 2289 // Check if messaging is enabled. 2290 if (empty($CFG->messaging)) { 2291 throw new moodle_exception('disabled', 'message'); 2292 } 2293 2294 $params = self::validate_parameters( 2295 self::get_unread_conversations_count_parameters(), 2296 array('useridto' => $useridto) 2297 ); 2298 2299 $context = context_system::instance(); 2300 self::validate_context($context); 2301 2302 $useridto = $params['useridto']; 2303 2304 if (!empty($useridto)) { 2305 if (core_user::is_real_user($useridto)) { 2306 $userto = core_user::get_user($useridto, '*', MUST_EXIST); 2307 } else { 2308 throw new moodle_exception('invaliduser'); 2309 } 2310 } else { 2311 $useridto = $USER->id; 2312 } 2313 2314 // Check if the current user is the receiver or just a privileged user. 2315 if ($useridto != $USER->id and !has_capability('moodle/site:readallmessages', $context)) { 2316 throw new moodle_exception('accessdenied', 'admin'); 2317 } 2318 2319 return \core_message\api::count_unread_conversations($userto); 2320 } 2321 2322 /** 2323 * Get unread conversations count return description. 2324 * 2325 * @return external_single_structure 2326 * @since 3.2 2327 */ 2328 public static function get_unread_conversations_count_returns() { 2329 return new external_value(PARAM_INT, 'The count of unread messages for the user'); 2330 } 2331 2332 /** 2333 * Get blocked users parameters description. 2334 * 2335 * @return external_function_parameters 2336 * @since 2.9 2337 */ 2338 public static function get_blocked_users_parameters() { 2339 return new external_function_parameters( 2340 array( 2341 'userid' => new external_value(PARAM_INT, 2342 'the user whose blocked users we want to retrieve', 2343 VALUE_REQUIRED), 2344 ) 2345 ); 2346 } 2347 2348 /** 2349 * Retrieve a list of users blocked 2350 * 2351 * @param int $userid the user whose blocked users we want to retrieve 2352 * @return external_description 2353 * @since 2.9 2354 */ 2355 public static function get_blocked_users($userid) { 2356 global $CFG, $USER, $PAGE; 2357 2358 // Warnings array, it can be empty at the end but is mandatory. 2359 $warnings = array(); 2360 2361 // Validate params. 2362 $params = array( 2363 'userid' => $userid 2364 ); 2365 $params = self::validate_parameters(self::get_blocked_users_parameters(), $params); 2366 $userid = $params['userid']; 2367 2368 // Validate context. 2369 $context = context_system::instance(); 2370 self::validate_context($context); 2371 2372 // Check if private messaging between users is allowed. 2373 if (empty($CFG->messaging)) { 2374 throw new moodle_exception('disabled', 'message'); 2375 } 2376 2377 $user = core_user::get_user($userid, '*', MUST_EXIST); 2378 core_user::require_active_user($user); 2379 2380 // Check if we have permissions for retrieve the information. 2381 $capability = 'moodle/site:manageallmessaging'; 2382 if (($USER->id != $userid) && !has_capability($capability, $context)) { 2383 throw new required_capability_exception($context, $capability, 'nopermissions', ''); 2384 } 2385 2386 // Now, we can get safely all the blocked users. 2387 $users = \core_message\api::get_blocked_users($user->id); 2388 2389 $blockedusers = array(); 2390 foreach ($users as $user) { 2391 $newuser = array( 2392 'id' => $user->id, 2393 'fullname' => fullname($user), 2394 ); 2395 2396 $userpicture = new user_picture($user); 2397 $userpicture->size = 1; // Size f1. 2398 $newuser['profileimageurl'] = $userpicture->get_url($PAGE)->out(false); 2399 2400 $blockedusers[] = $newuser; 2401 } 2402 2403 $results = array( 2404 'users' => $blockedusers, 2405 'warnings' => $warnings 2406 ); 2407 return $results; 2408 } 2409 2410 /** 2411 * Get blocked users return description. 2412 * 2413 * @return external_single_structure 2414 * @since 2.9 2415 */ 2416 public static function get_blocked_users_returns() { 2417 return new external_single_structure( 2418 array( 2419 'users' => new external_multiple_structure( 2420 new external_single_structure( 2421 array( 2422 'id' => new external_value(PARAM_INT, 'User ID'), 2423 'fullname' => new external_value(PARAM_NOTAGS, 'User full name'), 2424 'profileimageurl' => new external_value(PARAM_URL, 'User picture URL', VALUE_OPTIONAL) 2425 ) 2426 ), 2427 'List of blocked users' 2428 ), 2429 'warnings' => new external_warnings() 2430 ) 2431 ); 2432 } 2433 2434 /** 2435 * Returns description of method parameters 2436 * 2437 * @return external_function_parameters 2438 * @since 2.9 2439 */ 2440 public static function mark_message_read_parameters() { 2441 return new external_function_parameters( 2442 array( 2443 'messageid' => new external_value(PARAM_INT, 'id of the message in the messages table'), 2444 'timeread' => new external_value(PARAM_INT, 'timestamp for when the message should be marked read', 2445 VALUE_DEFAULT, 0) 2446 ) 2447 ); 2448 } 2449 2450 /** 2451 * Mark a single message as read, trigger message_viewed event 2452 * 2453 * @param int $messageid id of the message (in the message table) 2454 * @param int $timeread timestamp for when the message should be marked read 2455 * @return external_description 2456 * @throws invalid_parameter_exception 2457 * @throws moodle_exception 2458 * @since 2.9 2459 */ 2460 public static function mark_message_read($messageid, $timeread) { 2461 global $CFG, $DB, $USER; 2462 2463 // Check if private messaging between users is allowed. 2464 if (empty($CFG->messaging)) { 2465 throw new moodle_exception('disabled', 'message'); 2466 } 2467 2468 // Warnings array, it can be empty at the end but is mandatory. 2469 $warnings = array(); 2470 2471 // Validate params. 2472 $params = array( 2473 'messageid' => $messageid, 2474 'timeread' => $timeread 2475 ); 2476 $params = self::validate_parameters(self::mark_message_read_parameters(), $params); 2477 2478 if (empty($params['timeread'])) { 2479 $timeread = time(); 2480 } else { 2481 $timeread = $params['timeread']; 2482 } 2483 2484 // Validate context. 2485 $context = context_system::instance(); 2486 self::validate_context($context); 2487 2488 $sql = "SELECT m.*, mcm.userid as useridto 2489 FROM {messages} m 2490 INNER JOIN {message_conversations} mc 2491 ON m.conversationid = mc.id 2492 INNER JOIN {message_conversation_members} mcm 2493 ON mcm.conversationid = mc.id 2494 LEFT JOIN {message_user_actions} mua 2495 ON (mua.messageid = m.id AND mua.userid = ? AND mua.action = ?) 2496 WHERE mua.id is NULL 2497 AND mcm.userid != m.useridfrom 2498 AND m.id = ?"; 2499 $messageparams = []; 2500 $messageparams[] = $USER->id; 2501 $messageparams[] = \core_message\api::MESSAGE_ACTION_READ; 2502 $messageparams[] = $params['messageid']; 2503 $message = $DB->get_record_sql($sql, $messageparams, MUST_EXIST); 2504 2505 if ($message->useridto != $USER->id) { 2506 throw new invalid_parameter_exception('Invalid messageid, you don\'t have permissions to mark this message as read'); 2507 } 2508 2509 \core_message\api::mark_message_as_read($USER->id, $message, $timeread); 2510 2511 $results = array( 2512 'messageid' => $message->id, 2513 'warnings' => $warnings 2514 ); 2515 return $results; 2516 } 2517 2518 /** 2519 * Returns description of method result value 2520 * 2521 * @return external_description 2522 * @since 2.9 2523 */ 2524 public static function mark_message_read_returns() { 2525 return new external_single_structure( 2526 array( 2527 'messageid' => new external_value(PARAM_INT, 'the id of the message in the messages table'), 2528 'warnings' => new external_warnings() 2529 ) 2530 ); 2531 } 2532 2533 /** 2534 * Returns description of method parameters 2535 * 2536 * @return external_function_parameters 2537 */ 2538 public static function mark_notification_read_parameters() { 2539 return new external_function_parameters( 2540 array( 2541 'notificationid' => new external_value(PARAM_INT, 'id of the notification'), 2542 'timeread' => new external_value(PARAM_INT, 'timestamp for when the notification should be marked read', 2543 VALUE_DEFAULT, 0) 2544 ) 2545 ); 2546 } 2547 2548 /** 2549 * Mark a single notification as read. 2550 * 2551 * This will trigger a 'notification_viewed' event. 2552 * 2553 * @param int $notificationid id of the notification 2554 * @param int $timeread timestamp for when the notification should be marked read 2555 * @return external_description 2556 * @throws invalid_parameter_exception 2557 * @throws moodle_exception 2558 */ 2559 public static function mark_notification_read($notificationid, $timeread) { 2560 global $CFG, $DB, $USER; 2561 2562 // Warnings array, it can be empty at the end but is mandatory. 2563 $warnings = array(); 2564 2565 // Validate params. 2566 $params = array( 2567 'notificationid' => $notificationid, 2568 'timeread' => $timeread 2569 ); 2570 $params = self::validate_parameters(self::mark_notification_read_parameters(), $params); 2571 2572 if (empty($params['timeread'])) { 2573 $timeread = time(); 2574 } else { 2575 $timeread = $params['timeread']; 2576 } 2577 2578 // Validate context. 2579 $context = context_system::instance(); 2580 self::validate_context($context); 2581 2582 $notification = $DB->get_record('notifications', ['id' => $params['notificationid']], '*', MUST_EXIST); 2583 2584 if ($notification->useridto != $USER->id) { 2585 throw new invalid_parameter_exception('Invalid notificationid, you don\'t have permissions to mark this ' . 2586 'notification as read'); 2587 } 2588 2589 \core_message\api::mark_notification_as_read($notification, $timeread); 2590 2591 $results = array( 2592 'notificationid' => $notification->id, 2593 'warnings' => $warnings 2594 ); 2595 2596 return $results; 2597 } 2598 2599 /** 2600 * Returns description of method result value 2601 * 2602 * @return external_description 2603 */ 2604 public static function mark_notification_read_returns() { 2605 return new external_single_structure( 2606 array( 2607 'notificationid' => new external_value(PARAM_INT, 'id of the notification'), 2608 'warnings' => new external_warnings() 2609 ) 2610 ); 2611 } 2612 2613 /** 2614 * Mark all conversation messages as read parameters description. 2615 * 2616 * @return external_function_parameters 2617 * @since 3.6 2618 */ 2619 public static function mark_all_conversation_messages_as_read_parameters() { 2620 return new external_function_parameters( 2621 array( 2622 'userid' => new external_value(PARAM_INT, 'The user id who who we are marking the messages as read for'), 2623 'conversationid' => 2624 new external_value(PARAM_INT, 'The conversation id who who we are marking the messages as read for') 2625 ) 2626 ); 2627 } 2628 2629 /** 2630 * Mark all conversation messages as read function. 2631 * 2632 * @param int $userid The user id of who we want to delete the conversation for 2633 * @param int $conversationid The id of the conversations 2634 * @since 3.6 2635 */ 2636 public static function mark_all_conversation_messages_as_read(int $userid, int $conversationid) { 2637 global $CFG; 2638 2639 // Check if messaging is enabled. 2640 if (empty($CFG->messaging)) { 2641 throw new moodle_exception('disabled', 'message'); 2642 } 2643 2644 $params = array( 2645 'userid' => $userid, 2646 'conversationid' => $conversationid, 2647 ); 2648 $params = self::validate_parameters(self::mark_all_conversation_messages_as_read_parameters(), $params); 2649 2650 $context = context_system::instance(); 2651 self::validate_context($context); 2652 2653 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 2654 core_user::require_active_user($user); 2655 2656 if (\core_message\api::can_mark_all_messages_as_read($params['userid'], $params['conversationid'])) { 2657 \core_message\api::mark_all_messages_as_read($params['userid'], $params['conversationid']); 2658 } else { 2659 throw new moodle_exception('accessdenied', 'admin'); 2660 } 2661 } 2662 2663 /** 2664 * Mark all conversation messages as read return description. 2665 * 2666 * @return external_warnings 2667 * @since 3.6 2668 */ 2669 public static function mark_all_conversation_messages_as_read_returns() { 2670 return null; 2671 } 2672 2673 /** 2674 * Returns description of method parameters. 2675 * 2676 * @return external_function_parameters 2677 * @since 3.6 2678 */ 2679 public static function delete_conversations_by_id_parameters() { 2680 return new external_function_parameters( 2681 array( 2682 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the conversation for'), 2683 'conversationids' => new external_multiple_structure( 2684 new external_value(PARAM_INT, 'The id of the conversation'), 2685 'List of conversation IDs' 2686 ), 2687 ) 2688 ); 2689 } 2690 2691 /** 2692 * Deletes a conversation. 2693 * 2694 * @param int $userid The user id of who we want to delete the conversation for 2695 * @param int[] $conversationids The ids of the conversations 2696 * @return array 2697 * @throws moodle_exception 2698 * @since 3.6 2699 */ 2700 public static function delete_conversations_by_id($userid, array $conversationids) { 2701 global $CFG; 2702 2703 // Check if private messaging between users is allowed. 2704 if (empty($CFG->messaging)) { 2705 throw new moodle_exception('disabled', 'message'); 2706 } 2707 2708 // Validate params. 2709 $params = [ 2710 'userid' => $userid, 2711 'conversationids' => $conversationids, 2712 ]; 2713 $params = self::validate_parameters(self::delete_conversations_by_id_parameters(), $params); 2714 2715 // Validate context. 2716 $context = context_system::instance(); 2717 self::validate_context($context); 2718 2719 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 2720 core_user::require_active_user($user); 2721 2722 foreach ($params['conversationids'] as $conversationid) { 2723 if (\core_message\api::can_delete_conversation($user->id, $conversationid)) { 2724 \core_message\api::delete_conversation_by_id($user->id, $conversationid); 2725 } else { 2726 throw new moodle_exception("You do not have permission to delete the conversation '$conversationid'"); 2727 } 2728 } 2729 2730 return []; 2731 } 2732 2733 /** 2734 * Returns description of method result value. 2735 * 2736 * @return external_description 2737 * @since 3.6 2738 */ 2739 public static function delete_conversations_by_id_returns() { 2740 return new external_warnings(); 2741 } 2742 2743 /** 2744 * Returns description of method parameters 2745 * 2746 * @return external_function_parameters 2747 * @since 3.1 2748 */ 2749 public static function delete_message_parameters() { 2750 return new external_function_parameters( 2751 array( 2752 'messageid' => new external_value(PARAM_INT, 'The message id'), 2753 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for'), 2754 'read' => new external_value(PARAM_BOOL, 'If is a message read', VALUE_DEFAULT, true) 2755 ) 2756 ); 2757 } 2758 2759 /** 2760 * Deletes a message 2761 * 2762 * @param int $messageid the message id 2763 * @param int $userid the user id of who we want to delete the message for 2764 * @param bool $read if is a message read (default to true) 2765 * @return external_description 2766 * @throws moodle_exception 2767 * @since 3.1 2768 */ 2769 public static function delete_message($messageid, $userid, $read = true) { 2770 global $CFG; 2771 2772 // Check if private messaging between users is allowed. 2773 if (empty($CFG->messaging)) { 2774 throw new moodle_exception('disabled', 'message'); 2775 } 2776 2777 // Warnings array, it can be empty at the end but is mandatory. 2778 $warnings = array(); 2779 2780 // Validate params. 2781 $params = array( 2782 'messageid' => $messageid, 2783 'userid' => $userid, 2784 'read' => $read 2785 ); 2786 $params = self::validate_parameters(self::delete_message_parameters(), $params); 2787 2788 // Validate context. 2789 $context = context_system::instance(); 2790 self::validate_context($context); 2791 2792 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 2793 core_user::require_active_user($user); 2794 2795 if (\core_message\api::can_delete_message($user->id, $params['messageid'])) { 2796 $status = \core_message\api::delete_message($user->id, $params['messageid']); 2797 } else { 2798 throw new moodle_exception('You do not have permission to delete this message'); 2799 } 2800 2801 $results = array( 2802 'status' => $status, 2803 'warnings' => $warnings 2804 ); 2805 return $results; 2806 } 2807 2808 /** 2809 * Returns description of method result value 2810 * 2811 * @return external_description 2812 * @since 3.1 2813 */ 2814 public static function delete_message_returns() { 2815 return new external_single_structure( 2816 array( 2817 'status' => new external_value(PARAM_BOOL, 'True if the message was deleted, false otherwise'), 2818 'warnings' => new external_warnings() 2819 ) 2820 ); 2821 } 2822 2823 /** 2824 * Returns description of method parameters 2825 * 2826 * @return external_function_parameters 2827 * @since 3.2 2828 */ 2829 public static function message_processor_config_form_parameters() { 2830 return new external_function_parameters( 2831 array( 2832 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED), 2833 'name' => new external_value(PARAM_SAFEDIR, 'The name of the message processor'), 2834 'formvalues' => new external_multiple_structure( 2835 new external_single_structure( 2836 array( 2837 'name' => new external_value(PARAM_TEXT, 'name of the form element', VALUE_REQUIRED), 2838 'value' => new external_value(PARAM_RAW, 'value of the form element', VALUE_REQUIRED), 2839 ) 2840 ), 2841 'Config form values', 2842 VALUE_REQUIRED 2843 ), 2844 ) 2845 ); 2846 } 2847 2848 /** 2849 * Processes a message processor config form. 2850 * 2851 * @param int $userid the user id 2852 * @param string $name the name of the processor 2853 * @param array $formvalues the form values 2854 * @return external_description 2855 * @throws moodle_exception 2856 * @since 3.2 2857 */ 2858 public static function message_processor_config_form($userid, $name, $formvalues) { 2859 global $USER, $CFG; 2860 2861 $params = self::validate_parameters( 2862 self::message_processor_config_form_parameters(), 2863 array( 2864 'userid' => $userid, 2865 'name' => $name, 2866 'formvalues' => $formvalues, 2867 ) 2868 ); 2869 2870 $user = self::validate_preferences_permissions($params['userid']); 2871 2872 $processor = get_message_processor($params['name']); 2873 $preferences = []; 2874 $form = new stdClass(); 2875 2876 foreach ($params['formvalues'] as $formvalue) { 2877 // Curly braces to ensure interpretation is consistent between 2878 // php 5 and php 7. 2879 $form->{$formvalue['name']} = $formvalue['value']; 2880 } 2881 2882 $processor->process_form($form, $preferences); 2883 2884 if (!empty($preferences)) { 2885 set_user_preferences($preferences, $params['userid']); 2886 } 2887 } 2888 2889 /** 2890 * Returns description of method result value 2891 * 2892 * @return external_description 2893 * @since 3.2 2894 */ 2895 public static function message_processor_config_form_returns() { 2896 return null; 2897 } 2898 2899 /** 2900 * Returns description of method parameters 2901 * 2902 * @return external_function_parameters 2903 * @since 3.2 2904 */ 2905 public static function get_message_processor_parameters() { 2906 return new external_function_parameters( 2907 array( 2908 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user'), 2909 'name' => new external_value(PARAM_SAFEDIR, 'The name of the message processor', VALUE_REQUIRED), 2910 ) 2911 ); 2912 } 2913 2914 /** 2915 * Get a message processor. 2916 * 2917 * @param int $userid 2918 * @param string $name the name of the processor 2919 * @return external_description 2920 * @throws moodle_exception 2921 * @since 3.2 2922 */ 2923 public static function get_message_processor($userid, $name) { 2924 global $USER, $PAGE, $CFG; 2925 2926 // Check if messaging is enabled. 2927 if (empty($CFG->messaging)) { 2928 throw new moodle_exception('disabled', 'message'); 2929 } 2930 2931 $params = self::validate_parameters( 2932 self::get_message_processor_parameters(), 2933 array( 2934 'userid' => $userid, 2935 'name' => $name, 2936 ) 2937 ); 2938 2939 if (empty($params['userid'])) { 2940 $params['userid'] = $USER->id; 2941 } 2942 2943 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 2944 core_user::require_active_user($user); 2945 self::validate_context(context_user::instance($params['userid'])); 2946 2947 $processor = get_message_processor($params['name']); 2948 2949 $processoroutput = new \core_message\output\processor($processor, $user); 2950 $renderer = $PAGE->get_renderer('core_message'); 2951 2952 return $processoroutput->export_for_template($renderer); 2953 } 2954 2955 /** 2956 * Returns description of method result value 2957 * 2958 * @return external_description 2959 * @since 3.2 2960 */ 2961 public static function get_message_processor_returns() { 2962 return new external_function_parameters( 2963 array( 2964 'systemconfigured' => new external_value(PARAM_BOOL, 'Site configuration status'), 2965 'userconfigured' => new external_value(PARAM_BOOL, 'The user configuration status'), 2966 ) 2967 ); 2968 } 2969 2970 /** 2971 * Check that the user has enough permission to retrieve message or notifications preferences. 2972 * 2973 * @param int $userid the user id requesting the preferences 2974 * @return stdClass full user object 2975 * @throws moodle_exception 2976 * @since Moodle 3.2 2977 */ 2978 protected static function validate_preferences_permissions($userid) { 2979 global $USER; 2980 2981 if (empty($userid)) { 2982 $user = $USER; 2983 } else { 2984 $user = core_user::get_user($userid, '*', MUST_EXIST); 2985 core_user::require_active_user($user); 2986 } 2987 2988 $systemcontext = context_system::instance(); 2989 self::validate_context($systemcontext); 2990 2991 // Check access control. 2992 if ($user->id == $USER->id) { 2993 // Editing own message profile. 2994 require_capability('moodle/user:editownmessageprofile', $systemcontext); 2995 } else { 2996 // Teachers, parents, etc. 2997 $personalcontext = context_user::instance($user->id); 2998 require_capability('moodle/user:editmessageprofile', $personalcontext); 2999 } 3000 return $user; 3001 } 3002 3003 /** 3004 * Returns a notification or message preference structure. 3005 * 3006 * @return external_single_structure the structure 3007 * @since Moodle 3.2 3008 */ 3009 protected static function get_preferences_structure() { 3010 return new external_single_structure( 3011 array( 3012 'userid' => new external_value(PARAM_INT, 'User id'), 3013 'disableall' => new external_value(PARAM_INT, 'Whether all the preferences are disabled'), 3014 'processors' => new external_multiple_structure( 3015 new external_single_structure( 3016 array( 3017 'displayname' => new external_value(PARAM_TEXT, 'Display name'), 3018 'name' => new external_value(PARAM_PLUGIN, 'Processor name'), 3019 'hassettings' => new external_value(PARAM_BOOL, 'Whether has settings'), 3020 'contextid' => new external_value(PARAM_INT, 'Context id'), 3021 'userconfigured' => new external_value(PARAM_INT, 'Whether is configured by the user'), 3022 ) 3023 ), 3024 'Config form values' 3025 ), 3026 'components' => new external_multiple_structure( 3027 new external_single_structure( 3028 array( 3029 'displayname' => new external_value(PARAM_TEXT, 'Display name'), 3030 'notifications' => new external_multiple_structure( 3031 new external_single_structure( 3032 array( 3033 'displayname' => new external_value(PARAM_TEXT, 'Display name'), 3034 'preferencekey' => new external_value(PARAM_ALPHANUMEXT, 'Preference key'), 3035 'processors' => new external_multiple_structure( 3036 new external_single_structure( 3037 array( 3038 'displayname' => new external_value(PARAM_TEXT, 'Display name'), 3039 'name' => new external_value(PARAM_PLUGIN, 'Processor name'), 3040 'locked' => new external_value(PARAM_BOOL, 'Is locked by admin?'), 3041 'lockedmessage' => new external_value(PARAM_TEXT, 3042 'Text to display if locked', VALUE_OPTIONAL), 3043 'userconfigured' => new external_value(PARAM_INT, 'Is configured?'), 3044 'loggedin' => new external_single_structure( 3045 array( 3046 'name' => new external_value(PARAM_NOTAGS, 'Name'), 3047 'displayname' => new external_value(PARAM_TEXT, 'Display name'), 3048 'checked' => new external_value(PARAM_BOOL, 'Is checked?'), 3049 ) 3050 ), 3051 'loggedoff' => new external_single_structure( 3052 array( 3053 'name' => new external_value(PARAM_NOTAGS, 'Name'), 3054 'displayname' => new external_value(PARAM_TEXT, 'Display name'), 3055 'checked' => new external_value(PARAM_BOOL, 'Is checked?'), 3056 ) 3057 ), 3058 ) 3059 ), 3060 'Processors values for this notification' 3061 ), 3062 ) 3063 ), 3064 'List of notificaitons for the component' 3065 ), 3066 ) 3067 ), 3068 'Available components' 3069 ), 3070 ) 3071 ); 3072 } 3073 3074 /** 3075 * Returns description of method parameters 3076 * 3077 * @return external_function_parameters 3078 * @since 3.2 3079 */ 3080 public static function get_user_notification_preferences_parameters() { 3081 return new external_function_parameters( 3082 array( 3083 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0) 3084 ) 3085 ); 3086 } 3087 3088 /** 3089 * Get the notification preferences for a given user. 3090 * 3091 * @param int $userid id of the user, 0 for current user 3092 * @return external_description 3093 * @throws moodle_exception 3094 * @since 3.2 3095 */ 3096 public static function get_user_notification_preferences($userid = 0) { 3097 global $PAGE; 3098 3099 $params = self::validate_parameters( 3100 self::get_user_notification_preferences_parameters(), 3101 array( 3102 'userid' => $userid, 3103 ) 3104 ); 3105 $user = self::validate_preferences_permissions($params['userid']); 3106 3107 $processors = get_message_processors(); 3108 $providers = message_get_providers_for_user($user->id); 3109 $preferences = \core_message\api::get_all_message_preferences($processors, $providers, $user); 3110 $notificationlist = new \core_message\output\preferences\notification_list($processors, $providers, $preferences, $user); 3111 3112 $renderer = $PAGE->get_renderer('core_message'); 3113 3114 $result = array( 3115 'warnings' => array(), 3116 'preferences' => $notificationlist->export_for_template($renderer) 3117 ); 3118 return $result; 3119 } 3120 3121 /** 3122 * Returns description of method result value 3123 * 3124 * @return external_description 3125 * @since 3.2 3126 */ 3127 public static function get_user_notification_preferences_returns() { 3128 return new external_function_parameters( 3129 array( 3130 'preferences' => self::get_preferences_structure(), 3131 'warnings' => new external_warnings(), 3132 ) 3133 ); 3134 } 3135 3136 /** 3137 * Returns description of method parameters 3138 * 3139 * @return external_function_parameters 3140 * @since 3.2 3141 */ 3142 public static function get_user_message_preferences_parameters() { 3143 return new external_function_parameters( 3144 array( 3145 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0) 3146 ) 3147 ); 3148 } 3149 3150 /** 3151 * Get the notification preferences for a given user. 3152 * 3153 * @param int $userid id of the user, 0 for current user 3154 * @return external_description 3155 * @throws moodle_exception 3156 * @since 3.2 3157 */ 3158 public static function get_user_message_preferences($userid = 0) { 3159 global $CFG, $PAGE; 3160 3161 $params = self::validate_parameters( 3162 self::get_user_message_preferences_parameters(), 3163 array( 3164 'userid' => $userid, 3165 ) 3166 ); 3167 3168 $user = self::validate_preferences_permissions($params['userid']); 3169 3170 // Filter out enabled, available system_configured and user_configured processors only. 3171 $readyprocessors = array_filter(get_message_processors(), function($processor) { 3172 return $processor->enabled && 3173 $processor->configured && 3174 $processor->object->is_user_configured() && 3175 // Filter out processors that don't have and message preferences to configure. 3176 $processor->object->has_message_preferences(); 3177 }); 3178 3179 $providers = array_filter(message_get_providers_for_user($user->id), function($provider) { 3180 return $provider->component === 'moodle'; 3181 }); 3182 $preferences = \core_message\api::get_all_message_preferences($readyprocessors, $providers, $user); 3183 $notificationlistoutput = new \core_message\output\preferences\message_notification_list($readyprocessors, 3184 $providers, $preferences, $user); 3185 3186 $renderer = $PAGE->get_renderer('core_message'); 3187 3188 $entertosend = get_user_preferences('message_entertosend', $CFG->messagingdefaultpressenter, $user); 3189 3190 $result = array( 3191 'warnings' => array(), 3192 'preferences' => $notificationlistoutput->export_for_template($renderer), 3193 'blocknoncontacts' => \core_message\api::get_user_privacy_messaging_preference($user->id), 3194 'entertosend' => $entertosend 3195 ); 3196 return $result; 3197 } 3198 3199 /** 3200 * Returns description of method result value 3201 * 3202 * @return external_description 3203 * @since 3.2 3204 */ 3205 public static function get_user_message_preferences_returns() { 3206 return new external_function_parameters( 3207 array( 3208 'preferences' => self::get_preferences_structure(), 3209 'blocknoncontacts' => new external_value(PARAM_INT, 'Privacy messaging setting to define who can message you'), 3210 'entertosend' => new external_value(PARAM_BOOL, 'User preference for using enter to send messages'), 3211 'warnings' => new external_warnings(), 3212 ) 3213 ); 3214 } 3215 3216 /** 3217 * Returns description of method parameters for the favourite_conversations() method. 3218 * 3219 * @return external_function_parameters 3220 */ 3221 public static function set_favourite_conversations_parameters() { 3222 return new external_function_parameters( 3223 array( 3224 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0), 3225 'conversations' => new external_multiple_structure( 3226 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0) 3227 ) 3228 ) 3229 ); 3230 } 3231 3232 /** 3233 * Favourite a conversation, or list of conversations for a user. 3234 * 3235 * @param int $userid the id of the user, or 0 for the current user. 3236 * @param array $conversationids the list of conversations ids to favourite. 3237 * @return array 3238 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action. 3239 */ 3240 public static function set_favourite_conversations(int $userid, array $conversationids) { 3241 global $CFG, $USER; 3242 3243 // All the business logic checks that really shouldn't be in here. 3244 if (empty($CFG->messaging)) { 3245 throw new moodle_exception('disabled', 'message'); 3246 } 3247 $params = [ 3248 'userid' => $userid, 3249 'conversations' => $conversationids 3250 ]; 3251 $params = self::validate_parameters(self::set_favourite_conversations_parameters(), $params); 3252 $systemcontext = context_system::instance(); 3253 self::validate_context($systemcontext); 3254 3255 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) { 3256 throw new moodle_exception('You do not have permission to perform this action.'); 3257 } 3258 3259 foreach ($params['conversations'] as $conversationid) { 3260 \core_message\api::set_favourite_conversation($conversationid, $params['userid']); 3261 } 3262 3263 return []; 3264 } 3265 3266 /** 3267 * Return a description of the returns for the create_user_favourite_conversations() method. 3268 * 3269 * @return external_description 3270 */ 3271 public static function set_favourite_conversations_returns() { 3272 return new external_warnings(); 3273 } 3274 3275 /** 3276 * Returns description of method parameters for unfavourite_conversations() method. 3277 * 3278 * @return external_function_parameters 3279 */ 3280 public static function unset_favourite_conversations_parameters() { 3281 return new external_function_parameters( 3282 array( 3283 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0), 3284 'conversations' => new external_multiple_structure( 3285 new external_value(PARAM_INT, 'id of the conversation', VALUE_DEFAULT, 0) 3286 ) 3287 ) 3288 ); 3289 } 3290 3291 /** 3292 * Unfavourite a conversation, or list of conversations for a user. 3293 * 3294 * @param int $userid the id of the user, or 0 for the current user. 3295 * @param array $conversationids the list of conversations ids unset as favourites. 3296 * @return array 3297 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action. 3298 */ 3299 public static function unset_favourite_conversations(int $userid, array $conversationids) { 3300 global $CFG, $USER; 3301 3302 // All the business logic checks that really shouldn't be in here. 3303 if (empty($CFG->messaging)) { 3304 throw new moodle_exception('disabled', 'message'); 3305 } 3306 $params = [ 3307 'userid' => $userid, 3308 'conversations' => $conversationids 3309 ]; 3310 $params = self::validate_parameters(self::unset_favourite_conversations_parameters(), $params); 3311 $systemcontext = context_system::instance(); 3312 self::validate_context($systemcontext); 3313 3314 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) { 3315 throw new moodle_exception('You do not have permission to perform this action.'); 3316 } 3317 3318 foreach ($params['conversations'] as $conversationid) { 3319 \core_message\api::unset_favourite_conversation($conversationid, $params['userid']); 3320 } 3321 3322 return []; 3323 } 3324 3325 /** 3326 * Unset favourite conversations return description. 3327 * 3328 * @return external_description 3329 */ 3330 public static function unset_favourite_conversations_returns() { 3331 return new external_warnings(); 3332 } 3333 3334 /** 3335 * Returns description of method parameters for get_member_info() method. 3336 * 3337 * @return external_function_parameters 3338 */ 3339 public static function get_member_info_parameters() { 3340 return new external_function_parameters( 3341 array( 3342 'referenceuserid' => new external_value(PARAM_INT, 'id of the user'), 3343 'userids' => new external_multiple_structure( 3344 new external_value(PARAM_INT, 'id of members to get') 3345 ), 3346 'includecontactrequests' => new external_value(PARAM_BOOL, 'include contact requests in response', VALUE_DEFAULT, false), 3347 'includeprivacyinfo' => new external_value(PARAM_BOOL, 'include privacy info in response', VALUE_DEFAULT, false) 3348 ) 3349 ); 3350 } 3351 3352 /** 3353 * Returns conversation member info for the supplied users, relative to the supplied referenceuserid. 3354 * 3355 * This is the basic structure used when returning members, and includes information about the relationship between each member 3356 * and the referenceuser, such as a whether the referenceuser has marked the member as a contact, or has blocked them. 3357 * 3358 * @param int $referenceuserid the id of the user which check contact and blocked status. 3359 * @param array $userids 3360 * @return array the array of objects containing member info. 3361 * @throws moodle_exception if messaging is disabled or if the user cannot perform the action. 3362 */ 3363 public static function get_member_info( 3364 int $referenceuserid, 3365 array $userids, 3366 bool $includecontactrequests = false, 3367 bool $includeprivacyinfo = false 3368 ) { 3369 global $CFG, $USER; 3370 3371 // All the business logic checks that really shouldn't be in here. 3372 if (empty($CFG->messaging)) { 3373 throw new moodle_exception('disabled', 'message'); 3374 } 3375 $params = [ 3376 'referenceuserid' => $referenceuserid, 3377 'userids' => $userids, 3378 'includecontactrequests' => $includecontactrequests, 3379 'includeprivacyinfo' => $includeprivacyinfo 3380 ]; 3381 $params = self::validate_parameters(self::get_member_info_parameters(), $params); 3382 $systemcontext = context_system::instance(); 3383 self::validate_context($systemcontext); 3384 3385 if (($USER->id != $referenceuserid) && !has_capability('moodle/site:readallmessages', $systemcontext)) { 3386 throw new moodle_exception('You do not have permission to perform this action.'); 3387 } 3388 3389 return \core_message\helper::get_member_info( 3390 $params['referenceuserid'], 3391 $params['userids'], 3392 $params['includecontactrequests'], 3393 $params['includeprivacyinfo'] 3394 ); 3395 } 3396 3397 /** 3398 * Get member info return description. 3399 * 3400 * @return external_description 3401 */ 3402 public static function get_member_info_returns() { 3403 return new external_multiple_structure( 3404 self::get_conversation_member_structure() 3405 ); 3406 } 3407 3408 /** 3409 * Returns description of method parameters for get_conversation_counts() method. 3410 * 3411 * @return external_function_parameters 3412 */ 3413 public static function get_conversation_counts_parameters() { 3414 return new external_function_parameters( 3415 [ 3416 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0) 3417 ] 3418 ); 3419 } 3420 3421 /** 3422 * Returns an array of conversation counts for the various types of conversations, including favourites. 3423 * 3424 * Return format: 3425 * [ 3426 * 'favourites' => 0, 3427 * 'types' => [ 3428 * \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 3429 * \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0 3430 * ] 3431 * ] 3432 * 3433 * @param int $userid the id of the user whose counts we are fetching. 3434 * @return array the array of conversation counts, indexed by type. 3435 * @throws moodle_exception if the current user cannot perform this action. 3436 */ 3437 public static function get_conversation_counts(int $userid) { 3438 global $CFG, $USER; 3439 3440 // All the business logic checks that really shouldn't be in here. 3441 if (empty($CFG->messaging)) { 3442 throw new moodle_exception('disabled', 'message'); 3443 } 3444 3445 if (empty($userid)) { 3446 $userid = $USER->id; 3447 } 3448 3449 $params = ['userid' => $userid]; 3450 $params = self::validate_parameters(self::get_conversation_counts_parameters(), $params); 3451 3452 $systemcontext = context_system::instance(); 3453 self::validate_context($systemcontext); 3454 3455 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) { 3456 throw new moodle_exception('You do not have permission to perform this action.'); 3457 } 3458 3459 return \core_message\api::get_conversation_counts($params['userid']); 3460 } 3461 3462 /** 3463 * Get conversation counts return description. 3464 * 3465 * @return external_description 3466 */ 3467 public static function get_conversation_counts_returns() { 3468 return new external_single_structure( 3469 [ 3470 'favourites' => new external_value(PARAM_INT, 'Total number of favourite conversations'), 3471 'types' => new external_single_structure( 3472 [ 3473 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => new external_value(PARAM_INT, 3474 'Total number of individual conversations'), 3475 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => new external_value(PARAM_INT, 3476 'Total number of group conversations'), 3477 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => new external_value(PARAM_INT, 3478 'Total number of self conversations'), 3479 ] 3480 ), 3481 ] 3482 ); 3483 } 3484 3485 /** 3486 * Returns description of method parameters for get_unread_conversation_counts() method. 3487 * 3488 * @return external_function_parameters 3489 */ 3490 public static function get_unread_conversation_counts_parameters() { 3491 return new external_function_parameters( 3492 [ 3493 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_DEFAULT, 0) 3494 ] 3495 ); 3496 } 3497 3498 /** 3499 * Returns an array of unread conversation counts for the various types of conversations, including favourites. 3500 * 3501 * Return format: 3502 * [ 3503 * 'favourites' => 0, 3504 * 'types' => [ 3505 * \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => 0, 3506 * \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => 0 3507 * ] 3508 * ] 3509 * 3510 * @param int $userid the id of the user whose counts we are fetching. 3511 * @return array the array of unread conversation counts, indexed by type. 3512 * @throws moodle_exception if the current user cannot perform this action. 3513 */ 3514 public static function get_unread_conversation_counts(int $userid) { 3515 global $CFG, $USER; 3516 3517 // All the business logic checks that really shouldn't be in here. 3518 if (empty($CFG->messaging)) { 3519 throw new moodle_exception('disabled', 'message'); 3520 } 3521 3522 if (empty($userid)) { 3523 $userid = $USER->id; 3524 } 3525 3526 $params = ['userid' => $userid]; 3527 $params = self::validate_parameters(self::get_unread_conversation_counts_parameters(), $params); 3528 3529 $systemcontext = context_system::instance(); 3530 self::validate_context($systemcontext); 3531 3532 if (($USER->id != $params['userid']) && !has_capability('moodle/site:readallmessages', $systemcontext)) { 3533 throw new moodle_exception('You do not have permission to perform this action.'); 3534 } 3535 3536 return \core_message\api::get_unread_conversation_counts($params['userid']); 3537 } 3538 3539 /** 3540 * Get unread conversation counts return description. 3541 * 3542 * @return external_description 3543 */ 3544 public static function get_unread_conversation_counts_returns() { 3545 return new external_single_structure( 3546 [ 3547 'favourites' => new external_value(PARAM_INT, 'Total number of unread favourite conversations'), 3548 'types' => new external_single_structure( 3549 [ 3550 \core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => new external_value(PARAM_INT, 3551 'Total number of unread individual conversations'), 3552 \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP => new external_value(PARAM_INT, 3553 'Total number of unread group conversations'), 3554 \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF => new external_value(PARAM_INT, 3555 'Total number of unread self conversations'), 3556 ] 3557 ), 3558 ] 3559 ); 3560 } 3561 3562 /** 3563 * Returns description of method parameters 3564 * 3565 * @return external_function_parameters 3566 * @since 3.7 3567 */ 3568 public static function delete_message_for_all_users_parameters() { 3569 return new external_function_parameters( 3570 array( 3571 'messageid' => new external_value(PARAM_INT, 'The message id'), 3572 'userid' => new external_value(PARAM_INT, 'The user id of who we want to delete the message for all users') 3573 ) 3574 ); 3575 } 3576 /** 3577 * Deletes a message for all users 3578 * 3579 * @param int $messageid the message id 3580 * @param int $userid the user id of who we want to delete the message for all users, is no longer used. 3581 * @return external_description 3582 * @throws moodle_exception 3583 * @since 3.7 3584 */ 3585 public static function delete_message_for_all_users(int $messageid, int $userid) { 3586 global $CFG, $USER; 3587 3588 // Check if private messaging between users is allowed. 3589 if (empty($CFG->messaging)) { 3590 throw new moodle_exception('disabled', 'message'); 3591 } 3592 3593 // Validate params. 3594 $params = array( 3595 'messageid' => $messageid, 3596 'userid' => $userid 3597 ); 3598 $params = self::validate_parameters(self::delete_message_for_all_users_parameters(), $params); 3599 3600 // Validate context. 3601 $context = context_system::instance(); 3602 self::validate_context($context); 3603 3604 core_user::require_active_user($USER); 3605 3606 // Checks if a user can delete a message for all users. 3607 if (core_message\api::can_delete_message_for_all_users($USER->id, $params['messageid'])) { 3608 \core_message\api::delete_message_for_all_users($params['messageid']); 3609 } else { 3610 throw new moodle_exception('You do not have permission to delete this message for everyone.'); 3611 } 3612 3613 return []; 3614 } 3615 /** 3616 * Returns description of method result value 3617 * 3618 * @return external_description 3619 * @since 3.7 3620 */ 3621 public static function delete_message_for_all_users_returns() { 3622 return new external_warnings(); 3623 } 3624 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body