See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Workshop external API 19 * 20 * @package mod_workshop 21 * @category external 22 * @copyright 2017 Juan Leyva <juan@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 * @since Moodle 3.4 25 */ 26 27 defined('MOODLE_INTERNAL') || die; 28 29 require_once("$CFG->libdir/externallib.php"); 30 require_once($CFG->dirroot . '/mod/workshop/locallib.php'); 31 32 use mod_workshop\external\workshop_summary_exporter; 33 use mod_workshop\external\submission_exporter; 34 use mod_workshop\external\assessment_exporter; 35 36 /** 37 * Workshop external functions 38 * 39 * @package mod_workshop 40 * @category external 41 * @copyright 2017 Juan Leyva <juan@moodle.com> 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 * @since Moodle 3.4 44 */ 45 class mod_workshop_external extends external_api { 46 47 /** 48 * Describes the parameters for get_workshops_by_courses. 49 * 50 * @return external_function_parameters 51 * @since Moodle 3.4 52 */ 53 public static function get_workshops_by_courses_parameters() { 54 return new external_function_parameters ( 55 array( 56 'courseids' => new external_multiple_structure( 57 new external_value(PARAM_INT, 'Course id'), 'Array of course ids', VALUE_DEFAULT, array() 58 ), 59 ) 60 ); 61 } 62 63 /** 64 * Returns a list of workshops in a provided list of courses. 65 * If no list is provided all workshops that the user can view will be returned. 66 * 67 * @param array $courseids course ids 68 * @return array of warnings and workshops 69 * @since Moodle 3.4 70 */ 71 public static function get_workshops_by_courses($courseids = array()) { 72 global $PAGE; 73 74 $warnings = array(); 75 $returnedworkshops = array(); 76 77 $params = array( 78 'courseids' => $courseids, 79 ); 80 $params = self::validate_parameters(self::get_workshops_by_courses_parameters(), $params); 81 82 $mycourses = array(); 83 if (empty($params['courseids'])) { 84 $mycourses = enrol_get_my_courses(); 85 $params['courseids'] = array_keys($mycourses); 86 } 87 88 // Ensure there are courseids to loop through. 89 if (!empty($params['courseids'])) { 90 91 list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses); 92 $output = $PAGE->get_renderer('core'); 93 94 // Get the workshops in this course, this function checks users visibility permissions. 95 // We can avoid then additional validate_context calls. 96 $workshops = get_all_instances_in_courses("workshop", $courses); 97 foreach ($workshops as $workshop) { 98 99 $context = context_module::instance($workshop->coursemodule); 100 // Remove fields that are not from the workshop (added by get_all_instances_in_courses). 101 unset($workshop->coursemodule, $workshop->context, $workshop->visible, $workshop->section, $workshop->groupmode, 102 $workshop->groupingid); 103 104 $exporter = new workshop_summary_exporter($workshop, array('context' => $context)); 105 $returnedworkshops[] = $exporter->export($output); 106 } 107 } 108 109 $result = array( 110 'workshops' => $returnedworkshops, 111 'warnings' => $warnings 112 ); 113 return $result; 114 } 115 116 /** 117 * Describes the get_workshops_by_courses return value. 118 * 119 * @return external_single_structure 120 * @since Moodle 3.4 121 */ 122 public static function get_workshops_by_courses_returns() { 123 return new external_single_structure( 124 array( 125 'workshops' => new external_multiple_structure( 126 workshop_summary_exporter::get_read_structure() 127 ), 128 'warnings' => new external_warnings(), 129 ) 130 ); 131 } 132 133 /** 134 * Utility function for validating a workshop. 135 * 136 * @param int $workshopid workshop instance id 137 * @return array array containing the workshop object, course, context and course module objects 138 * @since Moodle 3.4 139 */ 140 protected static function validate_workshop($workshopid) { 141 global $DB, $USER; 142 143 // Request and permission validation. 144 $workshop = $DB->get_record('workshop', array('id' => $workshopid), '*', MUST_EXIST); 145 list($course, $cm) = get_course_and_cm_from_instance($workshop, 'workshop'); 146 147 $context = context_module::instance($cm->id); 148 self::validate_context($context); 149 150 $workshop = new workshop($workshop, $cm, $course); 151 152 return array($workshop, $course, $cm, $context); 153 } 154 155 156 /** 157 * Describes the parameters for get_workshop_access_information. 158 * 159 * @return external_external_function_parameters 160 * @since Moodle 3.4 161 */ 162 public static function get_workshop_access_information_parameters() { 163 return new external_function_parameters ( 164 array( 165 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.') 166 ) 167 ); 168 } 169 170 /** 171 * Return access information for a given workshop. 172 * 173 * @param int $workshopid workshop instance id 174 * @return array of warnings and the access information 175 * @since Moodle 3.4 176 * @throws moodle_exception 177 */ 178 public static function get_workshop_access_information($workshopid) { 179 global $USER; 180 181 $params = self::validate_parameters(self::get_workshop_access_information_parameters(), array('workshopid' => $workshopid)); 182 183 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 184 185 $result = array(); 186 // Return all the available capabilities. 187 $capabilities = load_capability_def('mod_workshop'); 188 foreach ($capabilities as $capname => $capdata) { 189 // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules. 190 $field = 'can' . str_replace('mod/workshop:', '', $capname); 191 $result[$field] = has_capability($capname, $context); 192 } 193 194 // Now, specific features access information. 195 $result['creatingsubmissionallowed'] = $workshop->creating_submission_allowed($USER->id); 196 $result['modifyingsubmissionallowed'] = $workshop->modifying_submission_allowed($USER->id); 197 $result['assessingallowed'] = $workshop->assessing_allowed($USER->id); 198 $result['assessingexamplesallowed'] = $workshop->assessing_examples_allowed(); 199 if (is_null($result['assessingexamplesallowed'])) { 200 $result['assessingexamplesallowed'] = false; 201 } 202 $result['examplesassessedbeforesubmission'] = $workshop->check_examples_assessed_before_submission($USER->id); 203 list($result['examplesassessedbeforeassessment'], $code) = $workshop->check_examples_assessed_before_assessment($USER->id); 204 205 $result['warnings'] = array(); 206 return $result; 207 } 208 209 /** 210 * Describes the get_workshop_access_information return value. 211 * 212 * @return external_single_structure 213 * @since Moodle 3.4 214 */ 215 public static function get_workshop_access_information_returns() { 216 217 $structure = array( 218 'creatingsubmissionallowed' => new external_value(PARAM_BOOL, 219 'Is the given user allowed to create their submission?'), 220 'modifyingsubmissionallowed' => new external_value(PARAM_BOOL, 221 'Is the user allowed to modify his existing submission?'), 222 'assessingallowed' => new external_value(PARAM_BOOL, 223 'Is the user allowed to create/edit his assessments?'), 224 'assessingexamplesallowed' => new external_value(PARAM_BOOL, 225 'Are reviewers allowed to create/edit their assessments of the example submissions?.'), 226 'examplesassessedbeforesubmission' => new external_value(PARAM_BOOL, 227 'Whether the given user has assessed all his required examples before submission 228 (always true if there are not examples to assess or not configured to check before submission).'), 229 'examplesassessedbeforeassessment' => new external_value(PARAM_BOOL, 230 'Whether the given user has assessed all his required examples before assessment 231 (always true if there are not examples to assessor not configured to check before assessment).'), 232 'warnings' => new external_warnings() 233 ); 234 235 $capabilities = load_capability_def('mod_workshop'); 236 foreach ($capabilities as $capname => $capdata) { 237 // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules. 238 $field = 'can' . str_replace('mod/workshop:', '', $capname); 239 $structure[$field] = new external_value(PARAM_BOOL, 'Whether the user has the capability ' . $capname . ' allowed.'); 240 } 241 242 return new external_single_structure($structure); 243 } 244 245 /** 246 * Describes the parameters for get_user_plan. 247 * 248 * @return external_external_function_parameters 249 * @since Moodle 3.4 250 */ 251 public static function get_user_plan_parameters() { 252 return new external_function_parameters ( 253 array( 254 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'), 255 'userid' => new external_value(PARAM_INT, 'User id (empty or 0 for current user).', VALUE_DEFAULT, 0), 256 ) 257 ); 258 } 259 260 /** 261 * Return the planner information for the given user. 262 * 263 * @param int $workshopid workshop instance id 264 * @param int $userid user id 265 * @return array of warnings and the user plan 266 * @since Moodle 3.4 267 * @throws moodle_exception 268 */ 269 public static function get_user_plan($workshopid, $userid = 0) { 270 global $USER; 271 272 $params = array( 273 'workshopid' => $workshopid, 274 'userid' => $userid, 275 ); 276 $params = self::validate_parameters(self::get_user_plan_parameters(), $params); 277 278 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 279 280 // Extra checks so only users with permissions can view other users plans. 281 if (empty($params['userid']) || $params['userid'] == $USER->id) { 282 $userid = $USER->id; 283 } else { 284 require_capability('moodle/course:manageactivities', $context); 285 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 286 core_user::require_active_user($user); 287 if (!$workshop->check_group_membership($user->id)) { 288 throw new moodle_exception('notingroup'); 289 } 290 $userid = $user->id; 291 } 292 293 // Get the user plan information ready for external functions. 294 $userplan = new workshop_user_plan($workshop, $userid); 295 $userplan = array('phases' => $userplan->phases, 'examples' => $userplan->get_examples()); 296 foreach ($userplan['phases'] as $phasecode => $phase) { 297 $phase->code = $phasecode; 298 $userplan['phases'][$phasecode] = (array) $phase; 299 foreach ($userplan['phases'][$phasecode]['tasks'] as $taskcode => $task) { 300 $task->code = $taskcode; 301 if ($task->link instanceof moodle_url) { 302 $task->link = $task->link->out(false); 303 } 304 $userplan['phases'][$phasecode]['tasks'][$taskcode] = (array) $task; 305 } 306 foreach ($userplan['phases'][$phasecode]['actions'] as $actioncode => $action) { 307 if ($action->url instanceof moodle_url) { 308 $action->url = $action->url->out(false); 309 } 310 $userplan['phases'][$phasecode]['actions'][$actioncode] = (array) $action; 311 } 312 } 313 314 $result['userplan'] = $userplan; 315 $result['warnings'] = array(); 316 return $result; 317 } 318 319 /** 320 * Describes the get_user_plan return value. 321 * 322 * @return external_single_structure 323 * @since Moodle 3.4 324 */ 325 public static function get_user_plan_returns() { 326 return new external_single_structure( 327 array( 328 'userplan' => new external_single_structure( 329 array( 330 'phases' => new external_multiple_structure( 331 new external_single_structure( 332 array( 333 'code' => new external_value(PARAM_INT, 'Phase code.'), 334 'title' => new external_value(PARAM_NOTAGS, 'Phase title.'), 335 'active' => new external_value(PARAM_BOOL, 'Whether is the active task.'), 336 'tasks' => new external_multiple_structure( 337 new external_single_structure( 338 array( 339 'code' => new external_value(PARAM_ALPHA, 'Task code.'), 340 'title' => new external_value(PARAM_RAW, 'Task title.'), 341 'link' => new external_value(PARAM_URL, 'Link to task.'), 342 'details' => new external_value(PARAM_RAW, 'Task details.', VALUE_OPTIONAL), 343 'completed' => new external_value(PARAM_NOTAGS, 344 'Completion information (maybe empty, maybe a boolean or generic info.'), 345 ) 346 ) 347 ), 348 'actions' => new external_multiple_structure( 349 new external_single_structure( 350 array( 351 'type' => new external_value(PARAM_ALPHA, 'Action type.', VALUE_OPTIONAL), 352 'label' => new external_value(PARAM_RAW, 'Action label.', VALUE_OPTIONAL), 353 'url' => new external_value(PARAM_URL, 'Link to action.'), 354 'method' => new external_value(PARAM_ALPHA, 'Get or post.', VALUE_OPTIONAL), 355 ) 356 ) 357 ), 358 ) 359 ) 360 ), 361 'examples' => new external_multiple_structure( 362 new external_single_structure( 363 array( 364 'id' => new external_value(PARAM_INT, 'Example submission id.'), 365 'title' => new external_value(PARAM_RAW, 'Example submission title.'), 366 'assessmentid' => new external_value(PARAM_INT, 'Example submission assessment id.'), 367 'grade' => new external_value(PARAM_FLOAT, 'The submission grade.'), 368 'gradinggrade' => new external_value(PARAM_FLOAT, 'The assessment grade.'), 369 ) 370 ) 371 ), 372 ) 373 ), 374 'warnings' => new external_warnings(), 375 ) 376 ); 377 } 378 379 /** 380 * Describes the parameters for view_workshop. 381 * 382 * @return external_function_parameters 383 * @since Moodle 3.4 384 */ 385 public static function view_workshop_parameters() { 386 return new external_function_parameters ( 387 array( 388 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id'), 389 ) 390 ); 391 } 392 393 /** 394 * Trigger the course module viewed event and update the module completion status. 395 * 396 * @param int $workshopid workshop instance id 397 * @return array of warnings and status result 398 * @since Moodle 3.4 399 * @throws moodle_exception 400 */ 401 public static function view_workshop($workshopid) { 402 403 $params = array('workshopid' => $workshopid); 404 $params = self::validate_parameters(self::view_workshop_parameters(), $params); 405 $warnings = array(); 406 407 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 408 409 $workshop->set_module_viewed(); 410 411 $result = array( 412 'status' => true, 413 'warnings' => $warnings, 414 ); 415 return $result; 416 } 417 418 /** 419 * Describes the view_workshop return value. 420 * 421 * @return external_single_structure 422 * @since Moodle 3.4 423 */ 424 public static function view_workshop_returns() { 425 return new external_single_structure( 426 array( 427 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 428 'warnings' => new external_warnings(), 429 ) 430 ); 431 } 432 433 /** 434 * Returns the description of the external function parameters. 435 * 436 * @return external_function_parameters 437 * @since Moodle 3.4 438 */ 439 public static function add_submission_parameters() { 440 return new external_function_parameters(array( 441 'workshopid' => new external_value(PARAM_INT, 'Workshop id'), 442 'title' => new external_value(PARAM_TEXT, 'Submission title'), 443 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''), 444 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE), 445 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content', 446 VALUE_DEFAULT, 0), 447 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0), 448 )); 449 } 450 451 /** 452 * Add a new submission to a given workshop. 453 * 454 * @param int $workshopid the workshop id 455 * @param string $title the submission title 456 * @param string $content the submission text content 457 * @param int $contentformat the format used for the content 458 * @param int $inlineattachmentsid the draft file area id for inline attachments in the content 459 * @param int $attachmentsid the draft file area id for attachments 460 * @return array Containing the new created submission id and warnings. 461 * @since Moodle 3.4 462 * @throws moodle_exception 463 */ 464 public static function add_submission($workshopid, $title, $content = '', $contentformat = FORMAT_MOODLE, 465 $inlineattachmentsid = 0, $attachmentsid = 0) { 466 global $USER; 467 468 $params = self::validate_parameters(self::add_submission_parameters(), array( 469 'workshopid' => $workshopid, 470 'title' => $title, 471 'content' => $content, 472 'contentformat' => $contentformat, 473 'inlineattachmentsid' => $inlineattachmentsid, 474 'attachmentsid' => $attachmentsid, 475 )); 476 $warnings = array(); 477 478 // Get and validate the workshop. 479 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 480 require_capability('mod/workshop:submit', $context); 481 482 // Check if we can submit now. 483 $canaddsubmission = $workshop->creating_submission_allowed($USER->id); 484 $canaddsubmission = $canaddsubmission && $workshop->check_examples_assessed_before_submission($USER->id); 485 if (!$canaddsubmission) { 486 throw new moodle_exception('nopermissions', 'error', '', 'add submission'); 487 } 488 489 // Prepare the submission object. 490 $submission = new stdClass; 491 $submission->id = null; 492 $submission->cmid = $cm->id; 493 $submission->example = 0; 494 $submission->title = trim($params['title']); 495 $submission->content_editor = array( 496 'text' => $params['content'], 497 'format' => $params['contentformat'], 498 'itemid' => $params['inlineattachmentsid'], 499 ); 500 $submission->attachment_filemanager = $params['attachmentsid']; 501 502 if (empty($submission->title)) { 503 throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title'); 504 } 505 506 $errors = $workshop->validate_submission_data((array) $submission); 507 // We can get several errors, return them in warnings. 508 if (!empty($errors)) { 509 $submission->id = 0; 510 foreach ($errors as $itemname => $message) { 511 $warnings[] = array( 512 'item' => $itemname, 513 'itemid' => 0, 514 'warningcode' => 'fielderror', 515 'message' => s($message) 516 ); 517 } 518 return array( 519 'status' => false, 520 'warnings' => $warnings 521 ); 522 } else { 523 $submission->id = $workshop->edit_submission($submission); 524 return array( 525 'status' => true, 526 'submissionid' => $submission->id, 527 'warnings' => $warnings 528 ); 529 } 530 } 531 532 /** 533 * Returns the description of the external function return value. 534 * 535 * @return external_description 536 * @since Moodle 3.4 537 */ 538 public static function add_submission_returns() { 539 return new external_single_structure(array( 540 'status' => new external_value(PARAM_BOOL, 'True if the submission was created false otherwise.'), 541 'submissionid' => new external_value(PARAM_INT, 'New workshop submission id.', VALUE_OPTIONAL), 542 'warnings' => new external_warnings() 543 )); 544 } 545 546 /** 547 * Returns the description of the external function parameters. 548 * 549 * @return external_function_parameters 550 * @since Moodle 3.4 551 */ 552 public static function update_submission_parameters() { 553 return new external_function_parameters(array( 554 'submissionid' => new external_value(PARAM_INT, 'Submission id'), 555 'title' => new external_value(PARAM_TEXT, 'Submission title'), 556 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''), 557 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE), 558 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content', 559 VALUE_DEFAULT, 0), 560 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0), 561 )); 562 } 563 564 565 /** 566 * Updates the given submission. 567 * 568 * @param int $submissionid the submission id 569 * @param string $title the submission title 570 * @param string $content the submission text content 571 * @param int $contentformat the format used for the content 572 * @param int $inlineattachmentsid the draft file area id for inline attachments in the content 573 * @param int $attachmentsid the draft file area id for attachments 574 * @return array whether the submission was updated and warnings. 575 * @since Moodle 3.4 576 * @throws moodle_exception 577 */ 578 public static function update_submission($submissionid, $title, $content = '', $contentformat = FORMAT_MOODLE, 579 $inlineattachmentsid = 0, $attachmentsid = 0) { 580 global $USER, $DB; 581 582 $params = self::validate_parameters(self::update_submission_parameters(), array( 583 'submissionid' => $submissionid, 584 'title' => $title, 585 'content' => $content, 586 'contentformat' => $contentformat, 587 'inlineattachmentsid' => $inlineattachmentsid, 588 'attachmentsid' => $attachmentsid, 589 )); 590 $warnings = array(); 591 592 // Get and validate the submission and workshop. 593 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); 594 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 595 require_capability('mod/workshop:submit', $context); 596 597 // Check if we can update the submission. 598 $canupdatesubmission = $submission->authorid == $USER->id; 599 $canupdatesubmission = $canupdatesubmission && $workshop->modifying_submission_allowed($USER->id); 600 $canupdatesubmission = $canupdatesubmission && $workshop->check_examples_assessed_before_submission($USER->id); 601 if (!$canupdatesubmission) { 602 throw new moodle_exception('nopermissions', 'error', '', 'update submission'); 603 } 604 605 // Prepare the submission object. 606 $submission->title = trim($params['title']); 607 if (empty($submission->title)) { 608 throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title'); 609 } 610 $submission->content_editor = array( 611 'text' => $params['content'], 612 'format' => $params['contentformat'], 613 'itemid' => $params['inlineattachmentsid'], 614 ); 615 $submission->attachment_filemanager = $params['attachmentsid']; 616 617 $errors = $workshop->validate_submission_data((array) $submission); 618 // We can get several errors, return them in warnings. 619 if (!empty($errors)) { 620 $status = false; 621 foreach ($errors as $itemname => $message) { 622 $warnings[] = array( 623 'item' => $itemname, 624 'itemid' => 0, 625 'warningcode' => 'fielderror', 626 'message' => s($message) 627 ); 628 } 629 } else { 630 $status = true; 631 $submission->id = $workshop->edit_submission($submission); 632 } 633 634 return array( 635 'status' => $status, 636 'warnings' => $warnings 637 ); 638 } 639 640 /** 641 * Returns the description of the external function return value. 642 * 643 * @return external_description 644 * @since Moodle 3.4 645 */ 646 public static function update_submission_returns() { 647 return new external_single_structure(array( 648 'status' => new external_value(PARAM_BOOL, 'True if the submission was updated false otherwise.'), 649 'warnings' => new external_warnings() 650 )); 651 } 652 653 /** 654 * Returns the description of the external function parameters. 655 * 656 * @return external_function_parameters 657 * @since Moodle 3.4 658 */ 659 public static function delete_submission_parameters() { 660 return new external_function_parameters( 661 array( 662 'submissionid' => new external_value(PARAM_INT, 'Submission id'), 663 ) 664 ); 665 } 666 667 668 /** 669 * Deletes the given submission. 670 * 671 * @param int $submissionid the submission id. 672 * @return array containing the result status and warnings. 673 * @since Moodle 3.4 674 * @throws moodle_exception 675 */ 676 public static function delete_submission($submissionid) { 677 global $USER, $DB; 678 679 $params = self::validate_parameters(self::delete_submission_parameters(), array('submissionid' => $submissionid)); 680 $warnings = array(); 681 682 // Get and validate the submission and workshop. 683 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); 684 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 685 686 // Check if we can delete the submission. 687 if (!has_capability('mod/workshop:deletesubmissions', $context)) { 688 require_capability('mod/workshop:submit', $context); 689 // We can delete our own submission, on time and not yet assessed. 690 $candeletesubmission = $submission->authorid == $USER->id; 691 $candeletesubmission = $candeletesubmission && $workshop->modifying_submission_allowed($USER->id); 692 $candeletesubmission = $candeletesubmission && count($workshop->get_assessments_of_submission($submission->id)) == 0; 693 if (!$candeletesubmission) { 694 throw new moodle_exception('nopermissions', 'error', '', 'delete submission'); 695 } 696 } 697 698 $workshop->delete_submission($submission); 699 700 return array( 701 'status' => true, 702 'warnings' => $warnings 703 ); 704 } 705 706 /** 707 * Returns the description of the external function return value. 708 * 709 * @return external_description 710 * @since Moodle 3.4 711 */ 712 public static function delete_submission_returns() { 713 return new external_single_structure(array( 714 'status' => new external_value(PARAM_BOOL, 'True if the submission was deleted.'), 715 'warnings' => new external_warnings() 716 )); 717 } 718 719 /** 720 * Helper method for returning the submission data according the current user capabilities and current phase. 721 * 722 * @param stdClass $submission the submission data 723 * @param workshop $workshop the workshop class 724 * @param bool $canviewauthorpublished whether the user has the capability mod/workshop:viewauthorpublished on 725 * @param bool $canviewauthornames whether the user has the capability mod/workshop:vviewauthornames on 726 * @param bool $canviewallsubmissions whether the user has the capability mod/workshop:viewallsubmissions on 727 * @return stdClass object with the submission data filtered 728 * @since Moodle 3.4 729 */ 730 protected static function prepare_submission_for_external($submission, workshop $workshop, $canviewauthorpublished = null, 731 $canviewauthornames = null, $canviewallsubmissions = null) { 732 global $USER; 733 734 if (is_null($canviewauthorpublished)) { 735 $canviewauthorpublished = has_capability('mod/workshop:viewauthorpublished', $workshop->context); 736 } 737 if (is_null($canviewauthornames)) { 738 $canviewauthornames = has_capability('mod/workshop:viewauthornames', $workshop->context); 739 } 740 if (is_null($canviewallsubmissions)) { 741 $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $workshop->context); 742 } 743 744 $ownsubmission = $submission->authorid == $USER->id; 745 if (!$canviewauthornames && !$ownsubmission) { 746 $submission->authorid = 0; 747 } 748 749 // Remove grade, gradeover, gradeoverby, feedbackauthor and timegraded for non-teachers or invalid phase. 750 // WS mod_workshop_external::get_grades should be used for retrieving grades by students. 751 if ($workshop->phase < workshop::PHASE_EVALUATION || !$canviewallsubmissions) { 752 $properties = submission_exporter::properties_definition(); 753 foreach ($properties as $attribute => $settings) { 754 // Special case, the feedbackauthor (and who did it) should be returned if the workshop is closed and 755 // the user can view it. 756 if (($attribute == 'feedbackauthor' || $attribute == 'gradeoverby') && 757 $workshop->phase == workshop::PHASE_CLOSED && $ownsubmission) { 758 continue; 759 } 760 if (!empty($settings['optional'])) { 761 unset($submission->{$attribute}); 762 } 763 } 764 } 765 return $submission; 766 } 767 768 /** 769 * Returns description of method parameters 770 * 771 * @return external_function_parameters 772 * @since Moodle 3.4 773 */ 774 public static function get_submissions_parameters() { 775 return new external_function_parameters( 776 array( 777 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'), 778 'userid' => new external_value(PARAM_INT, 'Get submissions done by this user. Use 0 or empty for the current user', 779 VALUE_DEFAULT, 0), 780 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group. 781 It will return submissions done by users in the given group.', 782 VALUE_DEFAULT, 0), 783 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0), 784 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page.', VALUE_DEFAULT, 0), 785 ) 786 ); 787 } 788 789 /** 790 * Retrieves all the workshop submissions visible by the current user or the one done by the given user 791 * (except example submissions). 792 * 793 * @param int $workshopid the workshop instance id 794 * @param int $userid get submissions done by this user 795 * @param int $groupid (optional) group id, 0 means that the function will determine the user group 796 * @param int $page page of records to return 797 * @param int $perpage number of records to return per page 798 * @return array of warnings and the entries 799 * @since Moodle 3.4 800 * @throws moodle_exception 801 */ 802 public static function get_submissions($workshopid, $userid = 0, $groupid = 0, $page = 0, $perpage = 0) { 803 global $PAGE, $USER; 804 805 $params = array('workshopid' => $workshopid, 'userid' => $userid, 'groupid' => $groupid, 806 'page' => $page, 'perpage' => $perpage); 807 $params = self::validate_parameters(self::get_submissions_parameters(), $params); 808 $submissions = $warnings = array(); 809 810 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 811 812 if (empty($params['groupid'])) { 813 // Check to see if groups are being used here. 814 if ($groupmode = groups_get_activity_groupmode($cm)) { 815 $groupid = groups_get_activity_group($cm); 816 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups). 817 if (!groups_group_visible($groupid, $course, $cm)) { 818 throw new moodle_exception('notingroup'); 819 } 820 } else { 821 $groupid = 0; 822 } 823 } 824 825 if (!empty($params['userid']) && $params['userid'] != $USER->id) { 826 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 827 core_user::require_active_user($user); 828 if (!$workshop->check_group_membership($user->id)) { 829 throw new moodle_exception('notingroup'); 830 } 831 } 832 833 $totalfilesize = 0; 834 list($submissionsrecords, $totalcount) = 835 $workshop->get_visible_submissions($params['userid'], $groupid, $params['page'], $params['perpage']); 836 837 if ($totalcount) { 838 839 $canviewauthorpublished = has_capability('mod/workshop:viewauthorpublished', $context); 840 $canviewauthornames = has_capability('mod/workshop:viewauthornames', $context); 841 $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $context); 842 843 $related = array('context' => $context); 844 foreach ($submissionsrecords as $submission) { 845 $submission = self::prepare_submission_for_external($submission, $workshop, $canviewauthorpublished, 846 $canviewauthornames, $canviewallsubmissions); 847 848 $exporter = new submission_exporter($submission, $related); 849 $submissions[] = $exporter->export($PAGE->get_renderer('core')); 850 } 851 852 // Retrieve total files size for the submissions (so external clients know how many data they'd need to download). 853 $fs = get_file_storage(); 854 $files = $fs->get_area_files($context->id, 'mod_workshop', array('submission_content', 'submission_attachment')); 855 foreach ($files as $file) { 856 if ($file->is_directory()) { 857 continue; 858 } 859 $totalfilesize += $file->get_filesize(); 860 } 861 } 862 863 return array( 864 'submissions' => $submissions, 865 'totalcount' => $totalcount, 866 'totalfilesize' => $totalfilesize, 867 ); 868 } 869 870 /** 871 * Returns description of method result value 872 * 873 * @return external_description 874 * @since Moodle 3.4 875 */ 876 public static function get_submissions_returns() { 877 return new external_single_structure( 878 array( 879 'submissions' => new external_multiple_structure( 880 submission_exporter::get_read_structure() 881 ), 882 'totalcount' => new external_value(PARAM_INT, 'Total count of submissions.'), 883 'totalfilesize' => new external_value(PARAM_INT, 'Total size (bytes) of the files attached to all the 884 submissions (even the ones not returned due to pagination).'), 885 'warnings' => new external_warnings() 886 ) 887 ); 888 } 889 890 /** 891 * Helper method for validating a submission. 892 * 893 * @param stdClass $submission submission object 894 * @param workshop $workshop workshop instance 895 * @return void 896 * @since Moodle 3.4 897 */ 898 protected static function validate_submission($submission, workshop $workshop) { 899 global $USER; 900 901 $workshopclosed = $workshop->phase == workshop::PHASE_CLOSED; 902 $canviewpublished = has_capability('mod/workshop:viewpublishedsubmissions', $workshop->context); 903 904 $canview = $submission->authorid == $USER->id; // I did it. 905 $canview = $canview || !empty($workshop->get_assessment_of_submission_by_user($submission->id, $USER->id)); // I reviewed. 906 $canview = $canview || has_capability('mod/workshop:viewallsubmissions', $workshop->context); // I can view all. 907 $canview = $canview || ($submission->published && $workshopclosed && $canviewpublished); // It has been published. 908 909 if ($canview) { 910 // Here we should check if the user share group. 911 if ($submission->authorid != $USER->id && 912 !groups_user_groups_visible($workshop->course, $submission->authorid, $workshop->cm)) { 913 throw new moodle_exception('notingroup'); 914 } 915 } else { 916 throw new moodle_exception('nopermissions', 'error', '', 'view submission'); 917 } 918 } 919 920 /** 921 * Returns the description of the external function parameters. 922 * 923 * @return external_function_parameters 924 * @since Moodle 3.4 925 */ 926 public static function get_submission_parameters() { 927 return new external_function_parameters( 928 array( 929 'submissionid' => new external_value(PARAM_INT, 'Submission id'), 930 ) 931 ); 932 } 933 934 935 /** 936 * Retrieves the given submission. 937 * 938 * @param int $submissionid the submission id 939 * @return array containing the submission and warnings. 940 * @since Moodle 3.4 941 * @throws moodle_exception 942 */ 943 public static function get_submission($submissionid) { 944 global $USER, $DB, $PAGE; 945 946 $params = self::validate_parameters(self::get_submission_parameters(), array('submissionid' => $submissionid)); 947 $warnings = array(); 948 949 // Get and validate the submission and workshop. 950 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); 951 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 952 953 self::validate_submission($submission, $workshop); 954 955 $submission = self::prepare_submission_for_external($submission, $workshop); 956 957 $related = array('context' => $context); 958 $exporter = new submission_exporter($submission, $related); 959 return array( 960 'submission' => $exporter->export($PAGE->get_renderer('core')), 961 'warnings' => $warnings 962 ); 963 } 964 965 /** 966 * Returns description of method result value 967 * 968 * @return external_description 969 * @since Moodle 3.4 970 */ 971 public static function get_submission_returns() { 972 return new external_single_structure( 973 array( 974 'submission' => submission_exporter::get_read_structure(), 975 'warnings' => new external_warnings() 976 ) 977 ); 978 } 979 980 /** 981 * Helper method for validating if the current user can view the submission assessments. 982 * 983 * @param stdClass $submission submission object 984 * @param workshop $workshop workshop instance 985 * @return void 986 * @since Moodle 3.4 987 */ 988 protected static function check_view_submission_assessments($submission, workshop $workshop) { 989 global $USER; 990 991 $ownsubmission = $submission->authorid == $USER->id; 992 $canview = has_capability('mod/workshop:viewallassessments', $workshop->context) || 993 ($ownsubmission && $workshop->assessments_available()); 994 995 if ($canview) { 996 // Here we should check if the user share group. 997 if ($submission->authorid != $USER->id && 998 !groups_user_groups_visible($workshop->course, $submission->authorid, $workshop->cm)) { 999 throw new moodle_exception('notingroup'); 1000 } 1001 } else { 1002 throw new moodle_exception('nopermissions', 'error', '', 'view assessment'); 1003 } 1004 } 1005 1006 /** 1007 * Helper method for returning the assessment data according the current user capabilities and current phase. 1008 * 1009 * @param stdClass $assessment the assessment data 1010 * @param workshop $workshop the workshop class 1011 * @return stdClass object with the assessment data filtered or null if is not viewable yet 1012 * @since Moodle 3.4 1013 */ 1014 protected static function prepare_assessment_for_external($assessment, workshop $workshop) { 1015 global $USER; 1016 static $canviewallassessments = null; 1017 static $canviewreviewers = null; 1018 static $canoverridegrades = null; 1019 1020 // Remove all the properties that does not belong to the assessment table. 1021 $properties = assessment_exporter::properties_definition(); 1022 foreach ($assessment as $key => $value) { 1023 if (!isset($properties[$key])) { 1024 unset($assessment->{$key}); 1025 } 1026 } 1027 1028 if (is_null($canviewallassessments)) { 1029 $canviewallassessments = has_capability('mod/workshop:viewallassessments', $workshop->context); 1030 } 1031 if (is_null($canviewreviewers)) { 1032 $canviewreviewers = has_capability('mod/workshop:viewreviewernames', $workshop->context); 1033 } 1034 if (is_null($canoverridegrades)) { 1035 $canoverridegrades = has_capability('mod/workshop:overridegrades', $workshop->context); 1036 } 1037 1038 $isreviewer = $assessment->reviewerid == $USER->id; 1039 1040 if (!$isreviewer && is_null($assessment->grade) && !$canviewallassessments) { 1041 // Students do not see peer-assessment that are not graded yet. 1042 return null; 1043 } 1044 1045 // Remove the feedback for the reviewer if: 1046 // I can't see it in the evaluation phase because I'm not a teacher or the reviewer AND 1047 // I can't see it in the assessment phase because I'm not a teacher. 1048 if (($workshop->phase < workshop::PHASE_EVALUATION || !($isreviewer || $canviewallassessments)) && 1049 ($workshop->phase < workshop::PHASE_ASSESSMENT || !$canviewallassessments) ) { 1050 // Remove all the feedback information (all the optional fields). 1051 foreach ($properties as $attribute => $settings) { 1052 if (!empty($settings['optional'])) { 1053 unset($assessment->{$attribute}); 1054 } 1055 } 1056 } 1057 1058 if (!$isreviewer && !$canviewreviewers) { 1059 $assessment->reviewerid = 0; 1060 } 1061 1062 return $assessment; 1063 } 1064 1065 /** 1066 * Returns the description of the external function parameters. 1067 * 1068 * @return external_function_parameters 1069 * @since Moodle 3.4 1070 */ 1071 public static function get_submission_assessments_parameters() { 1072 return new external_function_parameters( 1073 array( 1074 'submissionid' => new external_value(PARAM_INT, 'Submission id'), 1075 ) 1076 ); 1077 } 1078 1079 1080 /** 1081 * Retrieves the given submission assessments. 1082 * 1083 * @param int $submissionid the submission id 1084 * @return array containing the assessments and warnings. 1085 * @since Moodle 3.4 1086 * @throws moodle_exception 1087 */ 1088 public static function get_submission_assessments($submissionid) { 1089 global $USER, $DB, $PAGE; 1090 1091 $params = self::validate_parameters(self::get_submission_assessments_parameters(), array('submissionid' => $submissionid)); 1092 $warnings = $assessments = array(); 1093 1094 // Get and validate the submission and workshop. 1095 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); 1096 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 1097 1098 // Check that we can get the assessments and get them. 1099 self::check_view_submission_assessments($submission, $workshop); 1100 $assessmentsrecords = $workshop->get_assessments_of_submission($submission->id); 1101 1102 $related = array('context' => $context); 1103 foreach ($assessmentsrecords as $assessment) { 1104 $assessment = self::prepare_assessment_for_external($assessment, $workshop); 1105 if (empty($assessment)) { 1106 continue; 1107 } 1108 $exporter = new assessment_exporter($assessment, $related); 1109 $assessments[] = $exporter->export($PAGE->get_renderer('core')); 1110 } 1111 1112 return array( 1113 'assessments' => $assessments, 1114 'warnings' => $warnings 1115 ); 1116 } 1117 1118 /** 1119 * Returns description of method result value 1120 * 1121 * @return external_description 1122 * @since Moodle 3.4 1123 */ 1124 public static function get_submission_assessments_returns() { 1125 return new external_single_structure( 1126 array( 1127 'assessments' => new external_multiple_structure( 1128 assessment_exporter::get_read_structure() 1129 ), 1130 'warnings' => new external_warnings() 1131 ) 1132 ); 1133 } 1134 1135 /** 1136 * Returns the description of the external function parameters. 1137 * 1138 * @return external_function_parameters 1139 * @since Moodle 3.4 1140 */ 1141 public static function get_assessment_parameters() { 1142 return new external_function_parameters( 1143 array( 1144 'assessmentid' => new external_value(PARAM_INT, 'Assessment id'), 1145 ) 1146 ); 1147 } 1148 1149 1150 /** 1151 * Retrieves the given assessment. 1152 * 1153 * @param int $assessmentid the assessment id 1154 * @return array containing the assessment and warnings. 1155 * @since Moodle 3.4 1156 * @throws moodle_exception 1157 */ 1158 public static function get_assessment($assessmentid) { 1159 global $DB, $PAGE; 1160 1161 $params = self::validate_parameters(self::get_assessment_parameters(), array('assessmentid' => $assessmentid)); 1162 $warnings = array(); 1163 1164 // Get and validate the assessment, submission and workshop. 1165 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST); 1166 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST); 1167 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 1168 1169 // Check that we can get the assessment. 1170 $workshop->check_view_assessment($assessment, $submission); 1171 1172 $assessment = $workshop->get_assessment_by_id($assessment->id); 1173 $assessment = self::prepare_assessment_for_external($assessment, $workshop); 1174 if (empty($assessment)) { 1175 throw new moodle_exception('nopermissions', 'error', '', 'view assessment'); 1176 } 1177 $related = array('context' => $context); 1178 $exporter = new assessment_exporter($assessment, $related); 1179 1180 return array( 1181 'assessment' => $exporter->export($PAGE->get_renderer('core')), 1182 'warnings' => $warnings 1183 ); 1184 } 1185 1186 /** 1187 * Returns description of method result value 1188 * 1189 * @return external_description 1190 * @since Moodle 3.4 1191 */ 1192 public static function get_assessment_returns() { 1193 return new external_single_structure( 1194 array( 1195 'assessment' => assessment_exporter::get_read_structure(), 1196 'warnings' => new external_warnings() 1197 ) 1198 ); 1199 } 1200 1201 /** 1202 * Returns the description of the external function parameters. 1203 * 1204 * @return external_function_parameters 1205 * @since Moodle 3.4 1206 */ 1207 public static function get_assessment_form_definition_parameters() { 1208 return new external_function_parameters( 1209 array( 1210 'assessmentid' => new external_value(PARAM_INT, 'Assessment id'), 1211 'mode' => new external_value(PARAM_ALPHA, 'The form mode (assessment or preview)', VALUE_DEFAULT, 'assessment'), 1212 ) 1213 ); 1214 } 1215 1216 1217 /** 1218 * Retrieves the assessment form definition (data required to be able to display the assessment form). 1219 * 1220 * @param int $assessmentid the assessment id 1221 * @param string $mode the form mode (assessment or preview) 1222 * @return array containing the assessment and warnings. 1223 * @since Moodle 3.4 1224 * @throws moodle_exception 1225 */ 1226 public static function get_assessment_form_definition($assessmentid, $mode = 'assessment') { 1227 global $DB, $USER; 1228 1229 $params = self::validate_parameters( 1230 self::get_assessment_form_definition_parameters(), array('assessmentid' => $assessmentid, 'mode' => $mode) 1231 ); 1232 $warnings = $pending = array(); 1233 1234 if ($params['mode'] != 'assessment' && $params['mode'] != 'preview') { 1235 throw new invalid_parameter_exception('Invalid value for mode parameter (value: ' . $params['mode'] . ')'); 1236 } 1237 1238 // Get and validate the assessment, submission and workshop. 1239 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST); 1240 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST); 1241 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 1242 1243 // Check we can view the assessment (so we can get the form data). 1244 $workshop->check_view_assessment($assessment, $submission); 1245 1246 $cansetassessmentweight = has_capability('mod/workshop:allocate', $context); 1247 $pending = $workshop->get_pending_assessments_by_reviewer($assessment->reviewerid, $assessment->id); 1248 1249 // Retrieve the data from the strategy plugin. 1250 $strategy = $workshop->grading_strategy_instance(); 1251 $strategyname = str_replace('_strategy', '', get_class($strategy)); // Get strategy name. 1252 $mform = $strategy->get_assessment_form(null, $params['mode'], $assessment, true, 1253 array('editableweight' => $cansetassessmentweight, 'pending' => !empty($pending))); 1254 $formdata = $mform->get_customdata(); 1255 1256 $result = array( 1257 'dimenssionscount' => $formdata['nodims'], 1258 'descriptionfiles' => external_util::get_area_files($context->id, $strategyname, 'description'), 1259 'warnings' => $warnings 1260 ); 1261 // Include missing dimension fields. 1262 for ($i = 0; $i < $formdata['nodims']; $i++) { 1263 $formdata['fields']->{'gradeid__idx_' . $i} = 0; 1264 $formdata['fields']->{'peercomment__idx_' . $i} = ''; 1265 } 1266 1267 // Convert all the form data for external. 1268 foreach (array('options', 'fields', 'current') as $typeofdata) { 1269 $result[$typeofdata] = array(); 1270 1271 if (!empty($formdata[$typeofdata])) { 1272 $alldata = (array) $formdata[$typeofdata]; 1273 foreach ($alldata as $key => $val) { 1274 if (strpos($key, 'description__idx_')) { 1275 // Format dimension description. 1276 $id = str_replace('description__idx_', '', $key); 1277 list($val, $format) = external_format_text($val, $alldata['dimensionid__idx_' . $id . 'format'], 1278 $context->id, $strategyname, 'description', $alldata['dimensionid__idx_' . $id]); 1279 } 1280 $result[$typeofdata][] = array( 1281 'name' => $key, 1282 'value' => $val 1283 ); 1284 } 1285 } 1286 } 1287 1288 // Get dimensions info. 1289 $grader = $workshop->grading_strategy_instance(); 1290 $result['dimensionsinfo'] = $grader->get_dimensions_info(); 1291 1292 return $result; 1293 } 1294 1295 /** 1296 * Returns description of method result value 1297 * 1298 * @return external_description 1299 * @since Moodle 3.4 1300 */ 1301 public static function get_assessment_form_definition_returns() { 1302 return new external_single_structure( 1303 array( 1304 'dimenssionscount' => new external_value(PARAM_INT, 'The number of dimenssions used by the form.'), 1305 'descriptionfiles' => new external_files('Files in the description text'), 1306 'options' => new external_multiple_structure( 1307 new external_single_structure( 1308 array( 1309 'name' => new external_value(PARAM_ALPHANUMEXT, 'Option name.'), 1310 'value' => new external_value(PARAM_NOTAGS, 'Option value.') 1311 ) 1312 ), 'The form options.' 1313 ), 1314 'fields' => new external_multiple_structure( 1315 new external_single_structure( 1316 array( 1317 'name' => new external_value(PARAM_ALPHANUMEXT, 'Field name.'), 1318 'value' => new external_value(PARAM_RAW, 'Field default value.') 1319 ) 1320 ), 'The form fields.' 1321 ), 1322 'current' => new external_multiple_structure( 1323 new external_single_structure( 1324 array( 1325 'name' => new external_value(PARAM_ALPHANUMEXT, 'Field name.'), 1326 'value' => new external_value(PARAM_RAW, 'Current field value.') 1327 ) 1328 ), 'The current field values.' 1329 ), 1330 'dimensionsinfo' => new external_multiple_structure( 1331 new external_single_structure( 1332 array( 1333 'id' => new external_value(PARAM_INT, 'Dimension id.'), 1334 'min' => new external_value(PARAM_FLOAT, 'Minimum grade for the dimension.'), 1335 'max' => new external_value(PARAM_FLOAT, 'Maximum grade for the dimension.'), 1336 'weight' => new external_value(PARAM_TEXT, 'The weight of the dimension.'), 1337 'scale' => new external_value(PARAM_TEXT, 'Scale items (if used).', VALUE_OPTIONAL), 1338 ) 1339 ), 'The dimensions general information.' 1340 ), 1341 'warnings' => new external_warnings() 1342 ) 1343 ); 1344 } 1345 1346 /** 1347 * Returns the description of the external function parameters. 1348 * 1349 * @return external_function_parameters 1350 * @since Moodle 3.4 1351 */ 1352 public static function get_reviewer_assessments_parameters() { 1353 return new external_function_parameters( 1354 array( 1355 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'), 1356 'userid' => new external_value(PARAM_INT, 'User id who did the assessment review (empty or 0 for current user).', 1357 VALUE_DEFAULT, 0), 1358 ) 1359 ); 1360 } 1361 1362 1363 /** 1364 * Retrieves all the assessments reviewed by the given user. 1365 * 1366 * @param int $workshopid the workshop instance id 1367 * @param int $userid the reviewer user id 1368 * @return array containing the user assessments and warnings. 1369 * @since Moodle 3.4 1370 * @throws moodle_exception 1371 */ 1372 public static function get_reviewer_assessments($workshopid, $userid = 0) { 1373 global $USER, $DB, $PAGE; 1374 1375 $params = self::validate_parameters( 1376 self::get_reviewer_assessments_parameters(), array('workshopid' => $workshopid, 'userid' => $userid) 1377 ); 1378 $warnings = $assessments = array(); 1379 1380 // Get and validate the submission and workshop. 1381 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 1382 1383 // Extra checks so only users with permissions can view other users assessments. 1384 if (empty($params['userid']) || $params['userid'] == $USER->id) { 1385 $userid = $USER->id; 1386 list($assessed, $notice) = $workshop->check_examples_assessed_before_assessment($userid); 1387 if (!$assessed) { 1388 throw new moodle_exception($notice, 'mod_workshop'); 1389 } 1390 if ($workshop->phase < workshop::PHASE_ASSESSMENT) { // Can view assessments only in assessment phase onwards. 1391 throw new moodle_exception('nopermissions', 'error', '', 'view assessments'); 1392 } 1393 } else { 1394 require_capability('mod/workshop:viewallassessments', $context); 1395 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 1396 core_user::require_active_user($user); 1397 if (!$workshop->check_group_membership($user->id)) { 1398 throw new moodle_exception('notingroup'); 1399 } 1400 $userid = $user->id; 1401 } 1402 // Now get all my assessments (includes those pending review). 1403 $assessmentsrecords = $workshop->get_assessments_by_reviewer($userid); 1404 1405 $related = array('context' => $context); 1406 foreach ($assessmentsrecords as $assessment) { 1407 $assessment = self::prepare_assessment_for_external($assessment, $workshop); 1408 if (empty($assessment)) { 1409 continue; 1410 } 1411 $exporter = new assessment_exporter($assessment, $related); 1412 $assessments[] = $exporter->export($PAGE->get_renderer('core')); 1413 } 1414 1415 return array( 1416 'assessments' => $assessments, 1417 'warnings' => $warnings 1418 ); 1419 } 1420 1421 /** 1422 * Returns description of method result value 1423 * 1424 * @return external_description 1425 * @since Moodle 3.4 1426 */ 1427 public static function get_reviewer_assessments_returns() { 1428 return new external_single_structure( 1429 array( 1430 'assessments' => new external_multiple_structure( 1431 assessment_exporter::get_read_structure() 1432 ), 1433 'warnings' => new external_warnings() 1434 ) 1435 ); 1436 } 1437 1438 /** 1439 * Returns the description of the external function parameters. 1440 * 1441 * @return external_function_parameters 1442 * @since Moodle 3.4 1443 */ 1444 public static function update_assessment_parameters() { 1445 return new external_function_parameters( 1446 array( 1447 'assessmentid' => new external_value(PARAM_INT, 'Assessment id.'), 1448 'data' => new external_multiple_structure ( 1449 new external_single_structure( 1450 array( 1451 'name' => new external_value(PARAM_ALPHANUMEXT, 1452 'The assessment data (use WS get_assessment_form_definition for obtaining the data to sent). 1453 Apart from that data, you can optionally send: 1454 feedbackauthor (str); the feedback for the submission author 1455 feedbackauthorformat (int); the format of the feedbackauthor 1456 feedbackauthorinlineattachmentsid (int); the draft file area for the editor attachments 1457 feedbackauthorattachmentsid (int); the draft file area id for the feedback attachments' 1458 ), 1459 'value' => new external_value(PARAM_RAW, 'The value of the option.') 1460 ) 1461 ), 'Assessment data' 1462 ) 1463 ) 1464 ); 1465 } 1466 1467 1468 /** 1469 * Updates an assessment. 1470 * 1471 * @param int $assessmentid the assessment id 1472 * @param array $data the assessment data 1473 * @return array indicates if the assessment was updated, the new raw grade and possible warnings. 1474 * @since Moodle 3.4 1475 * @throws moodle_exception 1476 */ 1477 public static function update_assessment($assessmentid, $data) { 1478 global $DB, $USER; 1479 1480 $params = self::validate_parameters( 1481 self::update_assessment_parameters(), array('assessmentid' => $assessmentid, 'data' => $data) 1482 ); 1483 $warnings = array(); 1484 1485 // Get and validate the assessment, submission and workshop. 1486 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST); 1487 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST); 1488 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 1489 1490 // Check we can edit the assessment. 1491 $workshop->check_edit_assessment($assessment, $submission); 1492 1493 // Process data. 1494 $data = new stdClass; 1495 $data->feedbackauthor_editor = array(); 1496 1497 foreach ($params['data'] as $wsdata) { 1498 $name = trim($wsdata['name']); 1499 switch ($name) { 1500 case 'feedbackauthor': 1501 $data->feedbackauthor_editor['text'] = $wsdata['value']; 1502 break; 1503 case 'feedbackauthorformat': 1504 $data->feedbackauthor_editor['format'] = clean_param($wsdata['value'], PARAM_FORMAT); 1505 break; 1506 case 'feedbackauthorinlineattachmentsid': 1507 $data->feedbackauthor_editor['itemid'] = clean_param($wsdata['value'], PARAM_INT); 1508 break; 1509 case 'feedbackauthorattachmentsid': 1510 $data->feedbackauthorattachment_filemanager = clean_param($wsdata['value'], PARAM_INT); 1511 break; 1512 default: 1513 $data->{$wsdata['name']} = $wsdata['value']; // Validation will be done in the form->validation. 1514 } 1515 } 1516 1517 $cansetassessmentweight = has_capability('mod/workshop:allocate', $context); 1518 $pending = $workshop->get_pending_assessments_by_reviewer($assessment->reviewerid, $assessment->id); 1519 // Retrieve the data from the strategy plugin. 1520 $strategy = $workshop->grading_strategy_instance(); 1521 $mform = $strategy->get_assessment_form(null, 'assessment', $assessment, true, 1522 array('editableweight' => $cansetassessmentweight, 'pending' => !empty($pending))); 1523 1524 $errors = $mform->validation((array) $data, array()); 1525 // We can get several errors, return them in warnings. 1526 if (!empty($errors)) { 1527 $status = false; 1528 $rawgrade = null; 1529 foreach ($errors as $itemname => $message) { 1530 $warnings[] = array( 1531 'item' => $itemname, 1532 'itemid' => 0, 1533 'warningcode' => 'fielderror', 1534 'message' => s($message) 1535 ); 1536 } 1537 } else { 1538 $rawgrade = $workshop->edit_assessment($assessment, $submission, $data, $strategy); 1539 $status = true; 1540 } 1541 1542 return array( 1543 'status' => $status, 1544 'rawgrade' => $rawgrade, 1545 'warnings' => $warnings, 1546 ); 1547 } 1548 1549 /** 1550 * Returns description of method result value 1551 * 1552 * @return external_description 1553 * @since Moodle 3.4 1554 */ 1555 public static function update_assessment_returns() { 1556 return new external_single_structure( 1557 array( 1558 'status' => new external_value(PARAM_BOOL, 'status: true if the assessment was added or updated false otherwise.'), 1559 'rawgrade' => new external_value(PARAM_FLOAT, 'Raw percentual grade (0.00000 to 100.00000) for submission.', 1560 VALUE_OPTIONAL), 1561 'warnings' => new external_warnings() 1562 ) 1563 ); 1564 } 1565 1566 /** 1567 * Returns the description of the external function parameters. 1568 * 1569 * @return external_external_function_parameters 1570 * @since Moodle 3.4 1571 */ 1572 public static function get_grades_parameters() { 1573 return new external_function_parameters ( 1574 array( 1575 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'), 1576 'userid' => new external_value(PARAM_INT, 'User id (empty or 0 for current user).', VALUE_DEFAULT, 0), 1577 ) 1578 ); 1579 } 1580 1581 /** 1582 * Returns the grades information for the given workshop and user. 1583 * 1584 * @param int $workshopid workshop instance id 1585 * @param int $userid user id 1586 * @return array of warnings and the user plan 1587 * @since Moodle 3.4 1588 * @throws moodle_exception 1589 */ 1590 public static function get_grades($workshopid, $userid = 0) { 1591 global $USER; 1592 1593 $params = array( 1594 'workshopid' => $workshopid, 1595 'userid' => $userid, 1596 ); 1597 $params = self::validate_parameters(self::get_grades_parameters(), $params); 1598 $warnings = array(); 1599 1600 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 1601 1602 // Extra checks so only users with permissions can view other users plans. 1603 if (empty($params['userid']) || $params['userid'] == $USER->id) { 1604 $userid = $USER->id; 1605 } else { 1606 require_capability('mod/workshop:viewallassessments', $context); 1607 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 1608 core_user::require_active_user($user); 1609 if (!$workshop->check_group_membership($user->id)) { 1610 throw new moodle_exception('notingroup'); 1611 } 1612 $userid = $user->id; 1613 } 1614 1615 $finalgrades = $workshop->get_gradebook_grades($userid); 1616 1617 $result = array('warnings' => $warnings); 1618 if ($finalgrades !== false) { 1619 if (!empty($finalgrades->submissiongrade)) { 1620 if (is_numeric($finalgrades->submissiongrade->grade)) { 1621 $result['submissionrawgrade'] = $finalgrades->submissiongrade->grade; 1622 } 1623 $result['submissionlongstrgrade'] = $finalgrades->submissiongrade->str_long_grade; 1624 $result['submissiongradehidden'] = $finalgrades->submissiongrade->hidden; 1625 } 1626 if (!empty($finalgrades->assessmentgrade)) { 1627 if (is_numeric($finalgrades->assessmentgrade->grade)) { 1628 $result['assessmentrawgrade'] = $finalgrades->assessmentgrade->grade; 1629 } 1630 $result['assessmentlongstrgrade'] = $finalgrades->assessmentgrade->str_long_grade; 1631 $result['assessmentgradehidden'] = $finalgrades->assessmentgrade->hidden; 1632 } 1633 } 1634 1635 return $result; 1636 } 1637 1638 /** 1639 * Returns description of method result value. 1640 * 1641 * @return external_single_structure 1642 * @since Moodle 3.4 1643 */ 1644 public static function get_grades_returns() { 1645 return new external_single_structure( 1646 array( 1647 'assessmentrawgrade' => new external_value(PARAM_FLOAT, 'The assessment raw (numeric) grade.', VALUE_OPTIONAL), 1648 'assessmentlongstrgrade' => new external_value(PARAM_NOTAGS, 'The assessment string grade.', VALUE_OPTIONAL), 1649 'assessmentgradehidden' => new external_value(PARAM_BOOL, 'Whether the grade is hidden or not.', VALUE_OPTIONAL), 1650 'submissionrawgrade' => new external_value(PARAM_FLOAT, 'The submission raw (numeric) grade.', VALUE_OPTIONAL), 1651 'submissionlongstrgrade' => new external_value(PARAM_NOTAGS, 'The submission string grade.', VALUE_OPTIONAL), 1652 'submissiongradehidden' => new external_value(PARAM_BOOL, 'Whether the grade is hidden or not.', VALUE_OPTIONAL), 1653 'warnings' => new external_warnings(), 1654 ) 1655 ); 1656 } 1657 1658 /** 1659 * Returns the description of the external function parameters. 1660 * 1661 * @return external_function_parameters 1662 * @since Moodle 3.4 1663 */ 1664 public static function evaluate_assessment_parameters() { 1665 return new external_function_parameters( 1666 array( 1667 'assessmentid' => new external_value(PARAM_INT, 'Assessment id.'), 1668 'feedbacktext' => new external_value(PARAM_RAW, 'The feedback for the reviewer.', VALUE_DEFAULT, ''), 1669 'feedbackformat' => new external_value(PARAM_INT, 'The feedback format for text.', VALUE_DEFAULT, FORMAT_MOODLE), 1670 'weight' => new external_value(PARAM_INT, 'The new weight for the assessment.', VALUE_DEFAULT, 1), 1671 'gradinggradeover' => new external_value(PARAM_ALPHANUMEXT, 'The new grading grade.', VALUE_DEFAULT, ''), 1672 ) 1673 ); 1674 } 1675 1676 1677 /** 1678 * Evaluates an assessment (used by teachers for provide feedback to the reviewer). 1679 * 1680 * @param int $assessmentid the assessment id 1681 * @param str $feedbacktext the feedback for the reviewer 1682 * @param int $feedbackformat the feedback format for the reviewer text 1683 * @param int $weight the new weight for the assessment 1684 * @param mixed $gradinggradeover the new grading grade (empty for no overriding the grade) 1685 * @return array containing the status and warnings. 1686 * @since Moodle 3.4 1687 * @throws moodle_exception 1688 */ 1689 public static function evaluate_assessment($assessmentid, $feedbacktext = '', $feedbackformat = FORMAT_MOODLE, $weight = 1, 1690 $gradinggradeover = '') { 1691 global $DB; 1692 1693 $params = self::validate_parameters( 1694 self::evaluate_assessment_parameters(), 1695 array( 1696 'assessmentid' => $assessmentid, 1697 'feedbacktext' => $feedbacktext, 1698 'feedbackformat' => $feedbackformat, 1699 'weight' => $weight, 1700 'gradinggradeover' => $gradinggradeover, 1701 ) 1702 ); 1703 $warnings = array(); 1704 1705 // Get and validate the assessment, submission and workshop. 1706 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST); 1707 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST); 1708 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 1709 1710 // Check we can evaluate the assessment. 1711 $workshop->check_view_assessment($assessment, $submission); 1712 $cansetassessmentweight = has_capability('mod/workshop:allocate', $context); 1713 $canoverridegrades = has_capability('mod/workshop:overridegrades', $context); 1714 if (!$canoverridegrades && !$cansetassessmentweight) { 1715 throw new moodle_exception('nopermissions', 'error', '', 'evaluate assessments'); 1716 } 1717 1718 // Process data. 1719 $data = new stdClass; 1720 $data->asid = $assessment->id; 1721 $data->feedbackreviewer_editor = array( 1722 'text' => $params['feedbacktext'], 1723 'format' => $params['feedbackformat'], 1724 ); 1725 $data->weight = $params['weight']; 1726 $data->gradinggradeover = $params['gradinggradeover']; 1727 1728 $options = array( 1729 'editable' => true, 1730 'editableweight' => $cansetassessmentweight, 1731 'overridablegradinggrade' => $canoverridegrades 1732 ); 1733 $feedbackform = $workshop->get_feedbackreviewer_form(null, $assessment, $options); 1734 1735 $errors = $feedbackform->validation((array) $data, array()); 1736 // Extra checks for the new grade and weight. 1737 $possibleweights = workshop::available_assessment_weights_list(); 1738 if ($data->weight < 0 || $data->weight > max(array_keys($possibleweights))) { 1739 $errors['weight'] = 'The new weight must be higher or equal to 0 and cannot be higher than the maximum weight for 1740 assessment.'; 1741 } 1742 if (is_numeric($data->gradinggradeover) && 1743 ($data->gradinggradeover < 0 || $data->gradinggradeover > $workshop->gradinggrade)) { 1744 $errors['gradinggradeover'] = 'The new grade must be higher or equal to 0 and cannot be higher than the maximum grade 1745 for assessment.'; 1746 } 1747 1748 // We can get several errors, return them in warnings. 1749 if (!empty($errors)) { 1750 $status = false; 1751 foreach ($errors as $itemname => $message) { 1752 $warnings[] = array( 1753 'item' => $itemname, 1754 'itemid' => 0, 1755 'warningcode' => 'fielderror', 1756 'message' => s($message) 1757 ); 1758 } 1759 } else { 1760 $workshop->evaluate_assessment($assessment, $data, $cansetassessmentweight, $canoverridegrades); 1761 $status = true; 1762 } 1763 1764 return array( 1765 'status' => $status, 1766 'warnings' => $warnings, 1767 ); 1768 } 1769 1770 /** 1771 * Returns description of method result value 1772 * 1773 * @return external_description 1774 * @since Moodle 3.4 1775 */ 1776 public static function evaluate_assessment_returns() { 1777 return new external_single_structure( 1778 array( 1779 'status' => new external_value(PARAM_BOOL, 'status: true if the assessment was evaluated, false otherwise.'), 1780 'warnings' => new external_warnings() 1781 ) 1782 ); 1783 } 1784 1785 /** 1786 * Returns description of method parameters 1787 * 1788 * @return external_function_parameters 1789 * @since Moodle 3.4 1790 */ 1791 public static function get_grades_report_parameters() { 1792 return new external_function_parameters( 1793 array( 1794 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'), 1795 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group.', 1796 VALUE_DEFAULT, 0), 1797 'sortby' => new external_value(PARAM_ALPHA, 'sort by this element: lastname, firstname, submissiontitle, 1798 submissionmodified, submissiongrade, gradinggrade.', VALUE_DEFAULT, 'lastname'), 1799 'sortdirection' => new external_value(PARAM_ALPHA, 'sort direction: ASC or DESC', VALUE_DEFAULT, 'ASC'), 1800 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0), 1801 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page.', VALUE_DEFAULT, 0), 1802 ) 1803 ); 1804 } 1805 1806 /** 1807 * Retrieves the assessment grades report. 1808 * 1809 * @param int $workshopid the workshop instance id 1810 * @param int $groupid (optional) group id, 0 means that the function will determine the user group 1811 * @param string $sortby sort by this element 1812 * @param string $sortdirection sort direction: ASC or DESC 1813 * @param int $page page of records to return 1814 * @param int $perpage number of records to return per page 1815 * @return array of warnings and the report data 1816 * @since Moodle 3.4 1817 * @throws moodle_exception 1818 */ 1819 public static function get_grades_report($workshopid, $groupid = 0, $sortby = 'lastname', $sortdirection = 'ASC', 1820 $page = 0, $perpage = 0) { 1821 global $USER; 1822 1823 $params = array('workshopid' => $workshopid, 'groupid' => $groupid, 'sortby' => $sortby, 'sortdirection' => $sortdirection, 1824 'page' => $page, 'perpage' => $perpage); 1825 $params = self::validate_parameters(self::get_grades_report_parameters(), $params); 1826 $submissions = $warnings = array(); 1827 1828 $sortallowedvalues = array('lastname', 'firstname', 'submissiontitle', 'submissionmodified', 'submissiongrade', 1829 'gradinggrade'); 1830 if (!in_array($params['sortby'], $sortallowedvalues)) { 1831 throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $sortby . '),' . 1832 'allowed values are: ' . implode(',', $sortallowedvalues)); 1833 } 1834 1835 $sortdirection = strtoupper($params['sortdirection']); 1836 $directionallowedvalues = array('ASC', 'DESC'); 1837 if (!in_array($sortdirection, $directionallowedvalues)) { 1838 throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' . 1839 'allowed values are: ' . implode(',', $directionallowedvalues)); 1840 } 1841 1842 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); 1843 require_capability('mod/workshop:viewallassessments', $context); 1844 1845 if (!empty($params['groupid'])) { 1846 $groupid = $params['groupid']; 1847 // Determine is the group is visible to user. 1848 if (!groups_group_visible($groupid, $course, $cm)) { 1849 throw new moodle_exception('notingroup'); 1850 } 1851 } else { 1852 // Check to see if groups are being used here. 1853 if ($groupmode = groups_get_activity_groupmode($cm)) { 1854 $groupid = groups_get_activity_group($cm); 1855 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups). 1856 if (!groups_group_visible($groupid, $course, $cm)) { 1857 throw new moodle_exception('notingroup'); 1858 } 1859 } else { 1860 $groupid = 0; 1861 } 1862 } 1863 1864 if ($workshop->phase >= workshop::PHASE_SUBMISSION) { 1865 $showauthornames = has_capability('mod/workshop:viewauthornames', $context); 1866 $showreviewernames = has_capability('mod/workshop:viewreviewernames', $context); 1867 1868 if ($workshop->phase >= workshop::PHASE_EVALUATION) { 1869 $showsubmissiongrade = true; 1870 $showgradinggrade = true; 1871 } else { 1872 $showsubmissiongrade = false; 1873 $showgradinggrade = false; 1874 } 1875 1876 $data = $workshop->prepare_grading_report_data($USER->id, $groupid, $params['page'], $params['perpage'], 1877 $params['sortby'], $sortdirection); 1878 1879 if (!empty($data)) { 1880 // Populate the display options for the submissions report. 1881 $reportopts = new stdclass(); 1882 $reportopts->showauthornames = $showauthornames; 1883 $reportopts->showreviewernames = $showreviewernames; 1884 $reportopts->sortby = $params['sortby']; 1885 $reportopts->sorthow = $sortdirection; 1886 $reportopts->showsubmissiongrade = $showsubmissiongrade; 1887 $reportopts->showgradinggrade = $showgradinggrade; 1888 $reportopts->workshopphase = $workshop->phase; 1889 1890 $report = new workshop_grading_report($data, $reportopts); 1891 return array( 1892 'report' => $report->export_data_for_external(), 1893 'warnings' => array(), 1894 ); 1895 } 1896 } 1897 throw new moodle_exception('nothingfound', 'workshop'); 1898 } 1899 1900 /** 1901 * Returns description of method result value 1902 * 1903 * @return external_description 1904 * @since Moodle 3.4 1905 */ 1906 public static function get_grades_report_returns() { 1907 1908 $reviewstructure = new external_single_structure( 1909 array( 1910 'userid' => new external_value(PARAM_INT, 'The id of the user (0 when is configured to do not display names).'), 1911 'assessmentid' => new external_value(PARAM_INT, 'The id of the assessment.'), 1912 'submissionid' => new external_value(PARAM_INT, 'The id of the submission assessed.'), 1913 'grade' => new external_value(PARAM_FLOAT, 'The grade for submission.'), 1914 'gradinggrade' => new external_value(PARAM_FLOAT, 'The grade for assessment.'), 1915 'gradinggradeover' => new external_value(PARAM_FLOAT, 'The aggregated grade overrided.'), 1916 'weight' => new external_value(PARAM_INT, 'The weight of the assessment for aggregation.'), 1917 ) 1918 ); 1919 1920 return new external_single_structure( 1921 array( 1922 'report' => new external_single_structure( 1923 array( 1924 'grades' => new external_multiple_structure( 1925 new external_single_structure( 1926 array( 1927 'userid' => new external_value(PARAM_INT, 'The id of the user being displayed in the report.'), 1928 'submissionid' => new external_value(PARAM_INT, 'Submission id.'), 1929 'submissiontitle' => new external_value(PARAM_RAW, 'Submission title.'), 1930 'submissionmodified' => new external_value(PARAM_INT, 'Timestamp submission was updated.'), 1931 'submissiongrade' => new external_value(PARAM_FLOAT, 'Aggregated grade for the submission.', 1932 VALUE_OPTIONAL), 1933 'gradinggrade' => new external_value(PARAM_FLOAT, 'Computed grade for the assessment.', 1934 VALUE_OPTIONAL), 1935 'submissiongradeover' => new external_value(PARAM_FLOAT, 'Grade for the assessment overrided 1936 by the teacher.', VALUE_OPTIONAL), 1937 'submissiongradeoverby' => new external_value(PARAM_INT, 'The id of the user who overrided 1938 the grade.', VALUE_OPTIONAL), 1939 'submissionpublished' => new external_value(PARAM_INT, 'Whether is a submission published.', 1940 VALUE_OPTIONAL), 1941 'reviewedby' => new external_multiple_structure($reviewstructure, 'The users who reviewed the 1942 user submission.', VALUE_OPTIONAL), 1943 'reviewerof' => new external_multiple_structure($reviewstructure, 'The assessments the user 1944 reviewed.', VALUE_OPTIONAL), 1945 ) 1946 ) 1947 ), 1948 'totalcount' => new external_value(PARAM_INT, 'Number of total submissions.'), 1949 ) 1950 ), 1951 'warnings' => new external_warnings() 1952 ) 1953 ); 1954 } 1955 1956 /** 1957 * Describes the parameters for view_submission. 1958 * 1959 * @return external_function_parameters 1960 * @since Moodle 3.4 1961 */ 1962 public static function view_submission_parameters() { 1963 return new external_function_parameters ( 1964 array( 1965 'submissionid' => new external_value(PARAM_INT, 'Submission id'), 1966 ) 1967 ); 1968 } 1969 1970 /** 1971 * Trigger the submission viewed event. 1972 * 1973 * @param int $submissionid submission id 1974 * @return array of warnings and status result 1975 * @since Moodle 3.4 1976 * @throws moodle_exception 1977 */ 1978 public static function view_submission($submissionid) { 1979 global $DB; 1980 1981 $params = self::validate_parameters(self::view_submission_parameters(), array('submissionid' => $submissionid)); 1982 $warnings = array(); 1983 1984 // Get and validate the submission and workshop. 1985 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); 1986 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 1987 1988 self::validate_submission($submission, $workshop); 1989 1990 $workshop->set_submission_viewed($submission); 1991 1992 $result = array( 1993 'status' => true, 1994 'warnings' => $warnings, 1995 ); 1996 return $result; 1997 } 1998 1999 /** 2000 * Describes the view_submission return value. 2001 * 2002 * @return external_single_structure 2003 * @since Moodle 3.4 2004 */ 2005 public static function view_submission_returns() { 2006 return new external_single_structure( 2007 array( 2008 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 2009 'warnings' => new external_warnings(), 2010 ) 2011 ); 2012 } 2013 2014 /** 2015 * Returns the description of the external function parameters. 2016 * 2017 * @return external_function_parameters 2018 * @since Moodle 3.4 2019 */ 2020 public static function evaluate_submission_parameters() { 2021 return new external_function_parameters( 2022 array( 2023 'submissionid' => new external_value(PARAM_INT, 'submission id.'), 2024 'feedbacktext' => new external_value(PARAM_RAW, 'The feedback for the author.', VALUE_DEFAULT, ''), 2025 'feedbackformat' => new external_value(PARAM_INT, 'The feedback format for text.', VALUE_DEFAULT, FORMAT_MOODLE), 2026 'published' => new external_value(PARAM_BOOL, 'Publish the submission for others?.', VALUE_DEFAULT, false), 2027 'gradeover' => new external_value(PARAM_ALPHANUMEXT, 'The new submission grade.', VALUE_DEFAULT, ''), 2028 ) 2029 ); 2030 } 2031 2032 2033 /** 2034 * Evaluates a submission (used by teachers for provide feedback or override the submission grade). 2035 * 2036 * @param int $submissionid the submission id 2037 * @param str $feedbacktext the feedback for the author 2038 * @param int $feedbackformat the feedback format for the reviewer text 2039 * @param bool $published whether to publish the submission for other users 2040 * @param mixed $gradeover the new submission grade (empty for no overriding the grade) 2041 * @return array containing the status and warnings. 2042 * @since Moodle 3.4 2043 * @throws moodle_exception 2044 */ 2045 public static function evaluate_submission($submissionid, $feedbacktext = '', $feedbackformat = FORMAT_MOODLE, $published = 1, 2046 $gradeover = '') { 2047 global $DB; 2048 2049 $params = self::validate_parameters( 2050 self::evaluate_submission_parameters(), 2051 array( 2052 'submissionid' => $submissionid, 2053 'feedbacktext' => $feedbacktext, 2054 'feedbackformat' => $feedbackformat, 2055 'published' => $published, 2056 'gradeover' => $gradeover, 2057 ) 2058 ); 2059 $warnings = array(); 2060 2061 // Get and validate the submission, submission and workshop. 2062 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); 2063 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); 2064 2065 // Check we can evaluate the submission. 2066 self::validate_submission($submission, $workshop); 2067 $canpublish = has_capability('mod/workshop:publishsubmissions', $context); 2068 $canoverride = ($workshop->phase == workshop::PHASE_EVALUATION && 2069 has_capability('mod/workshop:overridegrades', $context)); 2070 2071 if (!$canpublish && !$canoverride) { 2072 throw new moodle_exception('nopermissions', 'error', '', 'evaluate submission'); 2073 } 2074 2075 // Process data. 2076 $data = new stdClass; 2077 $data->id = $submission->id; 2078 $data->feedbackauthor_editor = array( 2079 'text' => $params['feedbacktext'], 2080 'format' => $params['feedbackformat'], 2081 ); 2082 $data->published = $params['published']; 2083 $data->gradeover = $params['gradeover']; 2084 2085 $options = array( 2086 'editable' => true, 2087 'editablepublished' => $canpublish, 2088 'overridablegrade' => $canoverride 2089 ); 2090 $feedbackform = $workshop->get_feedbackauthor_form(null, $submission, $options); 2091 2092 $errors = $feedbackform->validation((array) $data, array()); 2093 // Extra checks for the new grade (if set). 2094 if (is_numeric($data->gradeover) && $data->gradeover > $workshop->grade) { 2095 $errors['gradeover'] = 'The new grade cannot be higher than the maximum grade for submission.'; 2096 } 2097 2098 // We can get several errors, return them in warnings. 2099 if (!empty($errors)) { 2100 $status = false; 2101 foreach ($errors as $itemname => $message) { 2102 $warnings[] = array( 2103 'item' => $itemname, 2104 'itemid' => 0, 2105 'warningcode' => 'fielderror', 2106 'message' => s($message) 2107 ); 2108 } 2109 } else { 2110 $workshop->evaluate_submission($submission, $data, $canpublish, $canoverride); 2111 $status = true; 2112 } 2113 2114 return array( 2115 'status' => $status, 2116 'warnings' => $warnings, 2117 ); 2118 } 2119 2120 /** 2121 * Returns description of method result value 2122 * 2123 * @return external_description 2124 * @since Moodle 3.4 2125 */ 2126 public static function evaluate_submission_returns() { 2127 return new external_single_structure( 2128 array( 2129 'status' => new external_value(PARAM_BOOL, 'status: true if the submission was evaluated, false otherwise.'), 2130 'warnings' => new external_warnings() 2131 ) 2132 ); 2133 } 2134 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body