Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 use core_external\external_api; 18 use core_external\external_format_value; 19 use core_external\external_function_parameters; 20 use core_external\external_multiple_structure; 21 use core_external\external_single_structure; 22 use core_external\external_value; 23 use core_external\external_warnings; 24 use core_external\util; 25 26 /** 27 * External notes API 28 * 29 * @package core_notes 30 * @category external 31 * @copyright 2011 Jerome Mouneyrac 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 35 defined('MOODLE_INTERNAL') || die(); 36 37 require_once($CFG->dirroot . "/notes/lib.php"); 38 39 /** 40 * Notes external functions 41 * 42 * @package core_notes 43 * @category external 44 * @copyright 2011 Jerome Mouneyrac 45 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 46 * @since Moodle 2.2 47 */ 48 class core_notes_external extends external_api { 49 50 /** 51 * Returns description of method parameters 52 * 53 * @return external_function_parameters 54 * @since Moodle 2.2 55 */ 56 public static function create_notes_parameters() { 57 return new external_function_parameters( 58 array( 59 'notes' => new external_multiple_structure( 60 new external_single_structure( 61 array( 62 'userid' => new external_value(PARAM_INT, 'id of the user the note is about'), 63 'publishstate' => new external_value(PARAM_ALPHA, '\'personal\', \'course\' or \'site\''), 64 'courseid' => new external_value(PARAM_INT, 'course id of the note (in Moodle a note can only be created into a course, even for site and personal notes)'), 65 'text' => new external_value(PARAM_RAW, 'the text of the message - text or HTML'), 66 'format' => new external_format_value('text', VALUE_DEFAULT), 67 'clientnoteid' => new external_value(PARAM_ALPHANUMEXT, 'your own client id for the note. If this id is provided, the fail message id will be returned to you', VALUE_OPTIONAL), 68 ) 69 ) 70 ) 71 ) 72 ); 73 } 74 75 /** 76 * Create notes about some users 77 * Note: code should be matching the /notes/edit.php checks 78 * and the /user/addnote.php checks. (they are similar cheks) 79 * 80 * @param array $notes An array of notes to create. 81 * @return array (success infos and fail infos) 82 * @since Moodle 2.2 83 */ 84 public static function create_notes($notes = array()) { 85 global $CFG, $DB; 86 87 $params = self::validate_parameters(self::create_notes_parameters(), array('notes' => $notes)); 88 89 // Check if note system is enabled. 90 if (!$CFG->enablenotes) { 91 throw new moodle_exception('notesdisabled', 'notes'); 92 } 93 94 // Retrieve all courses. 95 $courseids = array(); 96 foreach ($params['notes'] as $note) { 97 $courseids[] = $note['courseid']; 98 } 99 $courses = $DB->get_records_list("course", "id", $courseids); 100 101 // Retrieve all users of the notes. 102 $userids = array(); 103 foreach ($params['notes'] as $note) { 104 $userids[] = $note['userid']; 105 } 106 list($sqluserids, $sqlparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED, 'userid_'); 107 $users = $DB->get_records_select("user", "id " . $sqluserids . " AND deleted = 0", $sqlparams); 108 109 $resultnotes = array(); 110 foreach ($params['notes'] as $note) { 111 112 $success = true; 113 $resultnote = array(); // The infos about the success of the operation. 114 115 // Check the course exists. 116 if (empty($courses[$note['courseid']])) { 117 $success = false; 118 $errormessage = get_string('invalidcourseid', 'error'); 119 } else { 120 // Ensure the current user is allowed to run this function. 121 $context = context_course::instance($note['courseid']); 122 self::validate_context($context); 123 require_capability('moodle/notes:manage', $context); 124 } 125 126 // Check the user exists. 127 if (empty($users[$note['userid']])) { 128 $success = false; 129 $errormessage = get_string('invaliduserid', 'notes', $note['userid']); 130 } 131 132 // Build the resultnote. 133 if (isset($note['clientnoteid'])) { 134 $resultnote['clientnoteid'] = $note['clientnoteid']; 135 } 136 137 if ($success) { 138 // Now we can create the note. 139 $dbnote = new stdClass; 140 $dbnote->courseid = $note['courseid']; 141 $dbnote->userid = $note['userid']; 142 // Need to support 'html' and 'text' format values for backward compatibility. 143 switch (strtolower($note['format'])) { 144 case 'html': 145 $textformat = FORMAT_HTML; 146 break; 147 case 'text': 148 $textformat = FORMAT_PLAIN; 149 default: 150 $textformat = util::validate_format($note['format']); 151 break; 152 } 153 $dbnote->content = $note['text']; 154 $dbnote->format = $textformat; 155 156 // Get the state ('personal', 'course', 'site'). 157 switch ($note['publishstate']) { 158 case 'personal': 159 $dbnote->publishstate = NOTES_STATE_DRAFT; 160 break; 161 case 'course': 162 $dbnote->publishstate = NOTES_STATE_PUBLIC; 163 break; 164 case 'site': 165 $dbnote->publishstate = NOTES_STATE_SITE; 166 $dbnote->courseid = SITEID; 167 break; 168 default: 169 break; 170 } 171 172 // TODO MDL-31119 performance improvement - if possible create a bulk functions for saving multiple notes at once 173 if (note_save($dbnote)) { // Note_save attribut an id in case of success. 174 $success = $dbnote->id; 175 } 176 177 $resultnote['noteid'] = $success; 178 } else { 179 // WARNINGS: for backward compatibility we return this errormessage. 180 // We should have thrown exceptions as these errors prevent results to be returned. 181 // See http://docs.moodle.org/dev/Errors_handling_in_web_services#When_to_send_a_warning_on_the_server_side . 182 $resultnote['noteid'] = -1; 183 $resultnote['errormessage'] = $errormessage; 184 } 185 186 $resultnotes[] = $resultnote; 187 } 188 189 return $resultnotes; 190 } 191 192 /** 193 * Returns description of method result value 194 * 195 * @return \core_external\external_description 196 * @since Moodle 2.2 197 */ 198 public static function create_notes_returns() { 199 return new external_multiple_structure( 200 new external_single_structure( 201 array( 202 'clientnoteid' => new external_value(PARAM_ALPHANUMEXT, 'your own id for the note', VALUE_OPTIONAL), 203 'noteid' => new external_value(PARAM_INT, 'ID of the created note when successful, -1 when failed'), 204 'errormessage' => new external_value(PARAM_TEXT, 'error message - if failed', VALUE_OPTIONAL) 205 ) 206 ) 207 ); 208 } 209 210 /** 211 * Returns description of delete_notes parameters 212 * 213 * @return external_function_parameters 214 * @since Moodle 2.5 215 */ 216 public static function delete_notes_parameters() { 217 return new external_function_parameters( 218 array( 219 "notes"=> new external_multiple_structure( 220 new external_value(PARAM_INT, 'ID of the note to be deleted'), 'Array of Note Ids to be deleted.' 221 ) 222 ) 223 ); 224 } 225 226 /** 227 * Delete notes about users. 228 * Note: code should be matching the /notes/delete.php checks. 229 * 230 * @param array $notes An array of ids for the notes to delete. 231 * @return null 232 * @since Moodle 2.5 233 */ 234 public static function delete_notes($notes = array()) { 235 global $CFG; 236 237 $params = self::validate_parameters(self::delete_notes_parameters(), array('notes' => $notes)); 238 239 // Check if note system is enabled. 240 if (!$CFG->enablenotes) { 241 throw new moodle_exception('notesdisabled', 'notes'); 242 } 243 $warnings = array(); 244 foreach ($params['notes'] as $noteid) { 245 $note = note_load($noteid); 246 if (isset($note->id)) { 247 // Ensure the current user is allowed to run this function. 248 $context = context_course::instance($note->courseid); 249 self::validate_context($context); 250 require_capability('moodle/notes:manage', $context); 251 note_delete($note); 252 } else { 253 $warnings[] = array('item'=>'note', 'itemid'=>$noteid, 'warningcode'=>'badid', 'message'=>'Note does not exist'); 254 } 255 } 256 return $warnings; 257 } 258 259 /** 260 * Returns description of delete_notes result value. 261 * 262 * @return \core_external\external_description 263 * @since Moodle 2.5 264 */ 265 public static function delete_notes_returns() { 266 return new external_warnings('item is always \'note\'', 267 'When errorcode is savedfailed the note could not be modified.' . 268 'When errorcode is badparam, an incorrect parameter was provided.' . 269 'When errorcode is badid, the note does not exist', 270 'errorcode can be badparam (incorrect parameter), savedfailed (could not be modified), or badid (note does not exist)'); 271 272 } 273 274 /** 275 * Returns description of get_notes parameters. 276 * 277 * @return external_function_parameters 278 * @since Moodle 2.5 279 */ 280 public static function get_notes_parameters() { 281 return new external_function_parameters( 282 array( 283 "notes"=> new external_multiple_structure( 284 new external_value(PARAM_INT, 'ID of the note to be retrieved'), 'Array of Note Ids to be retrieved.' 285 ) 286 ) 287 ); 288 } 289 290 /** 291 * Get notes about users. 292 * 293 * @param array $notes An array of ids for the notes to retrieve. 294 * @return null 295 * @since Moodle 2.5 296 */ 297 public static function get_notes($notes) { 298 global $CFG; 299 300 $params = self::validate_parameters(self::get_notes_parameters(), array('notes' => $notes)); 301 // Check if note system is enabled. 302 if (!$CFG->enablenotes) { 303 throw new moodle_exception('notesdisabled', 'notes'); 304 } 305 $resultnotes = array(); 306 foreach ($params['notes'] as $noteid) { 307 $resultnote = array(); 308 309 $note = note_load($noteid); 310 if (isset($note->id)) { 311 // Ensure the current user is allowed to run this function. 312 $context = context_course::instance($note->courseid); 313 self::validate_context($context); 314 require_capability('moodle/notes:view', $context); 315 list($gotnote['text'], $gotnote['format']) = util::format_text($note->content, 316 $note->format, 317 $context->id, 318 'notes', 319 '', 320 ''); 321 $gotnote['noteid'] = $note->id; 322 $gotnote['userid'] = $note->userid; 323 $gotnote['publishstate'] = $note->publishstate; 324 $gotnote['courseid'] = $note->courseid; 325 $resultnotes["notes"][] = $gotnote; 326 } else { 327 $resultnotes["warnings"][] = array('item' => 'note', 328 'itemid' => $noteid, 329 'warningcode' => 'badid', 330 'message' => 'Note does not exist'); 331 } 332 } 333 return $resultnotes; 334 } 335 336 /** 337 * Returns description of get_notes result value. 338 * 339 * @return \core_external\external_description 340 * @since Moodle 2.5 341 */ 342 public static function get_notes_returns() { 343 return new external_single_structure( 344 array( 345 'notes' => new external_multiple_structure( 346 new external_single_structure( 347 array( 348 'noteid' => new external_value(PARAM_INT, 'id of the note', VALUE_OPTIONAL), 349 'userid' => new external_value(PARAM_INT, 'id of the user the note is about', VALUE_OPTIONAL), 350 'publishstate' => new external_value(PARAM_ALPHA, '\'personal\', \'course\' or \'site\'', VALUE_OPTIONAL), 351 'courseid' => new external_value(PARAM_INT, 'course id of the note', VALUE_OPTIONAL), 352 'text' => new external_value(PARAM_RAW, 'the text of the message - text or HTML', VALUE_OPTIONAL), 353 'format' => new external_format_value('text', VALUE_OPTIONAL), 354 ), 'note' 355 ) 356 ), 357 'warnings' => new external_warnings('item is always \'note\'', 358 'When errorcode is savedfailed the note could not be modified.' . 359 'When errorcode is badparam, an incorrect parameter was provided.' . 360 'When errorcode is badid, the note does not exist', 361 'errorcode can be badparam (incorrect parameter), savedfailed (could not be modified), or badid (note does not exist)') 362 ) 363 ); 364 } 365 366 /** 367 * Returns description of update_notes parameters. 368 * 369 * @return external_function_parameters 370 * @since Moodle 2.5 371 */ 372 public static function update_notes_parameters() { 373 return new external_function_parameters( 374 array( 375 'notes' => new external_multiple_structure( 376 new external_single_structure( 377 array( 378 'id' => new external_value(PARAM_INT, 'id of the note'), 379 'publishstate' => new external_value(PARAM_ALPHA, '\'personal\', \'course\' or \'site\''), 380 'text' => new external_value(PARAM_RAW, 'the text of the message - text or HTML'), 381 'format' => new external_format_value('text', VALUE_DEFAULT), 382 ) 383 ), "Array of Notes", VALUE_DEFAULT, array() 384 ) 385 ) 386 ); 387 } 388 389 /** 390 * Update notes about users. 391 * 392 * @param array $notes An array of ids for the notes to update. 393 * @return array fail infos. 394 * @since Moodle 2.2 395 */ 396 public static function update_notes($notes = array()) { 397 global $CFG, $DB; 398 399 $params = self::validate_parameters(self::update_notes_parameters(), array('notes' => $notes)); 400 401 // Check if note system is enabled. 402 if (!$CFG->enablenotes) { 403 throw new moodle_exception('notesdisabled', 'notes'); 404 } 405 406 $warnings = array(); 407 foreach ($params['notes'] as $note) { 408 $notedetails = note_load($note['id']); 409 if (isset($notedetails->id)) { 410 // Ensure the current user is allowed to run this function. 411 $context = context_course::instance($notedetails->courseid); 412 self::validate_context($context); 413 require_capability('moodle/notes:manage', $context); 414 415 $dbnote = new stdClass; 416 $dbnote->id = $note['id']; 417 $dbnote->content = $note['text']; 418 $dbnote->format = util::validate_format($note['format']); 419 // Get the state ('personal', 'course', 'site'). 420 switch ($note['publishstate']) { 421 case 'personal': 422 $dbnote->publishstate = NOTES_STATE_DRAFT; 423 break; 424 case 'course': 425 $dbnote->publishstate = NOTES_STATE_PUBLIC; 426 break; 427 case 'site': 428 $dbnote->publishstate = NOTES_STATE_SITE; 429 $dbnote->courseid = SITEID; 430 break; 431 default: 432 $warnings[] = array('item' => 'note', 433 'itemid' => $note["id"], 434 'warningcode' => 'badparam', 435 'message' => 'Provided publishstate incorrect'); 436 break; 437 } 438 if (!note_save($dbnote)) { 439 $warnings[] = array('item' => 'note', 440 'itemid' => $note["id"], 441 'warningcode' => 'savedfailed', 442 'message' => 'Note could not be modified'); 443 } 444 } else { 445 $warnings[] = array('item' => 'note', 446 'itemid' => $note["id"], 447 'warningcode' => 'badid', 448 'message' => 'Note does not exist'); 449 } 450 } 451 return $warnings; 452 } 453 454 /** 455 * Returns description of update_notes result value. 456 * 457 * @return \core_external\external_description 458 * @since Moodle 2.5 459 */ 460 public static function update_notes_returns() { 461 return new external_warnings('item is always \'note\'', 462 'When errorcode is savedfailed the note could not be modified.' . 463 'When errorcode is badparam, an incorrect parameter was provided.' . 464 'When errorcode is badid, the note does not exist', 465 'errorcode can be badparam (incorrect parameter), savedfailed (could not be modified), or badid (note does not exist)'); 466 } 467 468 /** 469 * Returns description of method parameters 470 * 471 * @return external_function_parameters 472 * @since Moodle 2.9 473 */ 474 public static function get_course_notes_parameters() { 475 return new external_function_parameters( 476 array( 477 'courseid' => new external_value(PARAM_INT, 'course id, 0 for SITE'), 478 'userid' => new external_value(PARAM_INT, 'user id', VALUE_DEFAULT, 0), 479 ) 480 ); 481 } 482 483 /** 484 * Create a notes list 485 * 486 * @param int $courseid ID of the Course 487 * @param stdClass $context context object 488 * @param int $userid ID of the User 489 * @param int $state 490 * @param int $author 491 * @return array of notes 492 * @since Moodle 2.9 493 */ 494 protected static function create_note_list($courseid, $context, $userid, $state, $author = 0) { 495 $results = []; 496 $notes = note_list($courseid, $userid, $state, $author); 497 foreach ($notes as $key => $note) { 498 $note = (array)$note; 499 [$note['content'], $note['format']] = util::format_text( 500 $note['content'], 501 $note['format'], 502 $context->id, 503 '', 504 '', 505 0 506 ); 507 $results[$key] = $note; 508 } 509 return $results; 510 } 511 512 /** 513 * Get a list of course notes 514 * 515 * @param int $courseid ID of the Course 516 * @param int $userid ID of the User 517 * @return array of site, course and personal notes and warnings 518 * @since Moodle 2.9 519 * @throws moodle_exception 520 */ 521 public static function get_course_notes($courseid, $userid = 0) { 522 global $CFG, $USER; 523 524 if (empty($CFG->enablenotes)) { 525 throw new moodle_exception('notesdisabled', 'notes'); 526 } 527 528 $warnings = array(); 529 $arrayparams = array( 530 'courseid' => $courseid, 531 'userid' => $userid, 532 ); 533 $params = self::validate_parameters(self::get_course_notes_parameters(), $arrayparams); 534 535 if (empty($params['courseid'])) { 536 $params['courseid'] = SITEID; 537 } 538 $user = null; 539 if (!empty($params['userid'])) { 540 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 541 core_user::require_active_user($user); 542 } 543 544 $course = get_course($params['courseid']); 545 546 $systemcontext = context_system::instance(); 547 $canmanagesystemnotes = has_capability('moodle/notes:manage', $systemcontext); 548 549 if ($course->id == SITEID) { 550 $context = $systemcontext; 551 $canmanagecoursenotes = $canmanagesystemnotes; 552 } else { 553 $context = context_course::instance($course->id); 554 $canmanagecoursenotes = has_capability('moodle/notes:manage', $context); 555 } 556 self::validate_context($context); 557 558 $sitenotes = array(); 559 $coursenotes = array(); 560 $personalnotes = array(); 561 562 if ($course->id != SITEID) { 563 564 require_capability('moodle/notes:view', $context); 565 $sitenotes = self::create_note_list(0, $systemcontext, $params['userid'], NOTES_STATE_SITE); 566 $coursenotes = self::create_note_list($course->id, $context, $params['userid'], NOTES_STATE_PUBLIC); 567 $personalnotes = self::create_note_list($course->id, $context, $params['userid'], NOTES_STATE_DRAFT, 568 $USER->id); 569 } else { 570 if (has_capability('moodle/notes:view', $context)) { 571 $sitenotes = self::create_note_list(0, $context, $params['userid'], NOTES_STATE_SITE); 572 } 573 // It returns notes only for a specific user! 574 if (!empty($user)) { 575 $usercourses = enrol_get_users_courses($user->id, true); 576 foreach ($usercourses as $c) { 577 // All notes at course level, only if we have capability on every course. 578 if (has_capability('moodle/notes:view', context_course::instance($c->id))) { 579 $coursenotes += self::create_note_list($c->id, $context, $params['userid'], NOTES_STATE_PUBLIC); 580 } 581 } 582 } 583 } 584 585 $results = array( 586 'sitenotes' => $sitenotes, 587 'coursenotes' => $coursenotes, 588 'personalnotes' => $personalnotes, 589 'canmanagesystemnotes' => $canmanagesystemnotes, 590 'canmanagecoursenotes' => $canmanagecoursenotes, 591 'warnings' => $warnings 592 ); 593 return $results; 594 595 } 596 597 /** 598 * Returns array of note structure 599 * 600 * @return \core_external\external_description 601 * @since Moodle 2.9 602 */ 603 protected static function get_note_structure() { 604 return array( 605 'id' => new external_value(PARAM_INT, 'id of this note'), 606 'courseid' => new external_value(PARAM_INT, 'id of the course'), 607 'userid' => new external_value(PARAM_INT, 'user id'), 608 'content' => new external_value(PARAM_RAW, 'the content text formated'), 609 'format' => new external_format_value('content'), 610 'created' => new external_value(PARAM_INT, 'time created (timestamp)'), 611 'lastmodified' => new external_value(PARAM_INT, 'time of last modification (timestamp)'), 612 'usermodified' => new external_value(PARAM_INT, 'user id of the creator of this note'), 613 'publishstate' => new external_value(PARAM_ALPHA, "state of the note (i.e. draft, public, site) ") 614 ); 615 } 616 617 /** 618 * Returns description of method result value 619 * 620 * @return \core_external\external_description 621 * @since Moodle 2.9 622 */ 623 public static function get_course_notes_returns() { 624 return new external_single_structure( 625 array( 626 'sitenotes' => new external_multiple_structure( 627 new external_single_structure(self::get_note_structure() , ''), 'site notes', VALUE_OPTIONAL 628 ), 629 'coursenotes' => new external_multiple_structure( 630 new external_single_structure(self::get_note_structure() , ''), 'couse notes', VALUE_OPTIONAL 631 ), 632 'personalnotes' => new external_multiple_structure( 633 new external_single_structure(self::get_note_structure() , ''), 'personal notes', VALUE_OPTIONAL 634 ), 635 'canmanagesystemnotes' => new external_value(PARAM_BOOL, 'Whether the user can manage notes at system level.', 636 VALUE_OPTIONAL), 637 'canmanagecoursenotes' => new external_value(PARAM_BOOL, 'Whether the user can manage notes at the given course.', 638 VALUE_OPTIONAL), 639 'warnings' => new external_warnings() 640 ), 'notes' 641 ); 642 } 643 644 /** 645 * Returns description of method parameters 646 * 647 * @return external_function_parameters 648 * @since Moodle 2.9 649 */ 650 public static function view_notes_parameters() { 651 return new external_function_parameters( 652 array( 653 'courseid' => new external_value(PARAM_INT, 'course id, 0 for notes at system level'), 654 'userid' => new external_value(PARAM_INT, 'user id, 0 means view all the user notes', VALUE_DEFAULT, 0) 655 ) 656 ); 657 } 658 659 /** 660 * Simulates the web interface view of notes/index.php: trigger events 661 * 662 * @param int $courseid id of the course 663 * @param int $userid id of the user 664 * @return array of warnings and status result 665 * @since Moodle 2.9 666 * @throws moodle_exception 667 */ 668 public static function view_notes($courseid, $userid = 0) { 669 global $CFG; 670 require_once($CFG->dirroot . "/notes/lib.php"); 671 672 if (empty($CFG->enablenotes)) { 673 throw new moodle_exception('notesdisabled', 'notes'); 674 } 675 676 $warnings = array(); 677 $arrayparams = array( 678 'courseid' => $courseid, 679 'userid' => $userid 680 ); 681 $params = self::validate_parameters(self::view_notes_parameters(), $arrayparams); 682 683 if (empty($params['courseid'])) { 684 $params['courseid'] = SITEID; 685 } 686 687 $course = get_course($params['courseid']); 688 689 if ($course->id == SITEID) { 690 $context = context_system::instance(); 691 } else { 692 $context = context_course::instance($course->id); 693 } 694 695 // First of all, validate the context before do further permission checks. 696 self::validate_context($context); 697 require_capability('moodle/notes:view', $context); 698 699 if (!empty($params['userid'])) { 700 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 701 core_user::require_active_user($user); 702 703 if ($course->id != SITEID and !can_access_course($course, $user, '', true)) { 704 throw new moodle_exception('notenrolledprofile'); 705 } 706 } 707 708 note_view($context, $params['userid']); 709 710 $result = array(); 711 $result['status'] = true; 712 $result['warnings'] = $warnings; 713 return $result; 714 715 } 716 717 /** 718 * Returns description of method result value 719 * 720 * @return \core_external\external_description 721 * @since Moodle 2.9 722 */ 723 public static function view_notes_returns() { 724 return new external_single_structure( 725 array( 726 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 727 'warnings' => new external_warnings() 728 ) 729 ); 730 } 731 732 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body