[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * External assign API 19 * 20 * @package mod_assign 21 * @since Moodle 2.4 22 * @copyright 2012 Paul Charsley 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die; 27 28 require_once("$CFG->libdir/externallib.php"); 29 require_once("$CFG->dirroot/user/externallib.php"); 30 require_once("$CFG->dirroot/mod/assign/locallib.php"); 31 32 /** 33 * Assign functions 34 * @copyright 2012 Paul Charsley 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class mod_assign_external extends external_api { 38 39 /** 40 * Generate a warning in a standard structure for a known failure. 41 * 42 * @param int $assignmentid - The assignment 43 * @param string $warningcode - The key for the warning message 44 * @param string $detail - A description of the error 45 * @return array - Warning structure containing item, itemid, warningcode, message 46 */ 47 private static function generate_warning($assignmentid, $warningcode, $detail) { 48 $warningmessages = array( 49 'couldnotlock'=>'Could not lock the submission for this user.', 50 'couldnotunlock'=>'Could not unlock the submission for this user.', 51 'couldnotsubmitforgrading'=>'Could not submit assignment for grading.', 52 'couldnotrevealidentities'=>'Could not reveal identities.', 53 'couldnotgrantextensions'=>'Could not grant submission date extensions.', 54 'couldnotrevert'=>'Could not revert submission to draft.', 55 'invalidparameters'=>'Invalid parameters.', 56 'couldnotsavesubmission'=>'Could not save submission.', 57 'couldnotsavegrade'=>'Could not save grade.' 58 ); 59 60 $message = $warningmessages[$warningcode]; 61 if (empty($message)) { 62 $message = 'Unknown warning type.'; 63 } 64 65 return array('item'=>$detail, 66 'itemid'=>$assignmentid, 67 'warningcode'=>$warningcode, 68 'message'=>$message); 69 } 70 71 /** 72 * Describes the parameters for get_grades 73 * @return external_external_function_parameters 74 * @since Moodle 2.4 75 */ 76 public static function get_grades_parameters() { 77 return new external_function_parameters( 78 array( 79 'assignmentids' => new external_multiple_structure( 80 new external_value(PARAM_INT, 'assignment id'), 81 '1 or more assignment ids', 82 VALUE_REQUIRED), 83 'since' => new external_value(PARAM_INT, 84 'timestamp, only return records where timemodified >= since', 85 VALUE_DEFAULT, 0) 86 ) 87 ); 88 } 89 90 /** 91 * Returns grade information from assign_grades for the requested assignment ids 92 * @param int[] $assignmentids 93 * @param int $since only return records with timemodified >= since 94 * @return array of grade records for each requested assignment 95 * @since Moodle 2.4 96 */ 97 public static function get_grades($assignmentids, $since = 0) { 98 global $DB; 99 $params = self::validate_parameters(self::get_grades_parameters(), 100 array('assignmentids' => $assignmentids, 101 'since' => $since)); 102 103 $assignments = array(); 104 $warnings = array(); 105 $requestedassignmentids = $params['assignmentids']; 106 107 // Check the user is allowed to get the grades for the assignments requested. 108 $placeholders = array(); 109 list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED); 110 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ". 111 "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids; 112 $placeholders['modname'] = 'assign'; 113 $cms = $DB->get_records_sql($sql, $placeholders); 114 foreach ($cms as $cm) { 115 try { 116 $context = context_module::instance($cm->id); 117 self::validate_context($context); 118 require_capability('mod/assign:grade', $context); 119 } catch (Exception $e) { 120 $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance)); 121 $warning = array(); 122 $warning['item'] = 'assignment'; 123 $warning['itemid'] = $cm->instance; 124 $warning['warningcode'] = '1'; 125 $warning['message'] = 'No access rights in module context'; 126 $warnings[] = $warning; 127 } 128 } 129 130 // Create the query and populate an array of grade records from the recordset results. 131 if (count ($requestedassignmentids) > 0) { 132 $placeholders = array(); 133 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED); 134 135 $sql = "SELECT ag.id, 136 ag.assignment, 137 ag.userid, 138 ag.timecreated, 139 ag.timemodified, 140 ag.grader, 141 ag.grade, 142 ag.attemptnumber 143 FROM {assign_grades} ag, {assign_submission} s 144 WHERE s.assignment $inorequalsql 145 AND s.userid = ag.userid 146 AND s.latest = 1 147 AND s.attemptnumber = ag.attemptnumber 148 AND ag.timemodified >= :since 149 AND ag.assignment = s.assignment 150 ORDER BY ag.assignment, ag.id"; 151 152 $placeholders['since'] = $params['since']; 153 $rs = $DB->get_recordset_sql($sql, $placeholders); 154 $currentassignmentid = null; 155 $assignment = null; 156 foreach ($rs as $rd) { 157 $grade = array(); 158 $grade['id'] = $rd->id; 159 $grade['userid'] = $rd->userid; 160 $grade['timecreated'] = $rd->timecreated; 161 $grade['timemodified'] = $rd->timemodified; 162 $grade['grader'] = $rd->grader; 163 $grade['attemptnumber'] = $rd->attemptnumber; 164 $grade['grade'] = (string)$rd->grade; 165 166 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) { 167 if (!is_null($assignment)) { 168 $assignments[] = $assignment; 169 } 170 $assignment = array(); 171 $assignment['assignmentid'] = $rd->assignment; 172 $assignment['grades'] = array(); 173 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment)); 174 } 175 $assignment['grades'][] = $grade; 176 177 $currentassignmentid = $rd->assignment; 178 } 179 if (!is_null($assignment)) { 180 $assignments[] = $assignment; 181 } 182 $rs->close(); 183 } 184 foreach ($requestedassignmentids as $assignmentid) { 185 $warning = array(); 186 $warning['item'] = 'assignment'; 187 $warning['itemid'] = $assignmentid; 188 $warning['warningcode'] = '3'; 189 $warning['message'] = 'No grades found'; 190 $warnings[] = $warning; 191 } 192 193 $result = array(); 194 $result['assignments'] = $assignments; 195 $result['warnings'] = $warnings; 196 return $result; 197 } 198 199 /** 200 * Creates a grade single structure. 201 * 202 * @return external_single_structure a grade single structure. 203 * @since Moodle 3.1 204 */ 205 private static function get_grade_structure($required = VALUE_REQUIRED) { 206 return new external_single_structure( 207 array( 208 'id' => new external_value(PARAM_INT, 'grade id'), 209 'assignment' => new external_value(PARAM_INT, 'assignment id', VALUE_OPTIONAL), 210 'userid' => new external_value(PARAM_INT, 'student id'), 211 'attemptnumber' => new external_value(PARAM_INT, 'attempt number'), 212 'timecreated' => new external_value(PARAM_INT, 'grade creation time'), 213 'timemodified' => new external_value(PARAM_INT, 'grade last modified time'), 214 'grader' => new external_value(PARAM_INT, 'grader'), 215 'grade' => new external_value(PARAM_TEXT, 'grade'), 216 'gradefordisplay' => new external_value(PARAM_RAW, 'grade rendered into a format suitable for display', 217 VALUE_OPTIONAL), 218 ), 'grade information', $required 219 ); 220 } 221 222 /** 223 * Creates an assign_grades external_single_structure 224 * @return external_single_structure 225 * @since Moodle 2.4 226 */ 227 private static function assign_grades() { 228 return new external_single_structure( 229 array ( 230 'assignmentid' => new external_value(PARAM_INT, 'assignment id'), 231 'grades' => new external_multiple_structure(self::get_grade_structure()) 232 ) 233 ); 234 } 235 236 /** 237 * Describes the get_grades return value 238 * @return external_single_structure 239 * @since Moodle 2.4 240 */ 241 public static function get_grades_returns() { 242 return new external_single_structure( 243 array( 244 'assignments' => new external_multiple_structure(self::assign_grades(), 'list of assignment grade information'), 245 'warnings' => new external_warnings('item is always \'assignment\'', 246 'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module id', 247 'errorcode can be 3 (no grades found) or 1 (no permission to get grades)') 248 ) 249 ); 250 } 251 252 /** 253 * Returns description of method parameters 254 * 255 * @return external_function_parameters 256 * @since Moodle 2.4 257 */ 258 public static function get_assignments_parameters() { 259 return new external_function_parameters( 260 array( 261 'courseids' => new external_multiple_structure( 262 new external_value(PARAM_INT, 'course id, empty for retrieving all the courses where the user is enroled in'), 263 '0 or more course ids', 264 VALUE_DEFAULT, array() 265 ), 266 'capabilities' => new external_multiple_structure( 267 new external_value(PARAM_CAPABILITY, 'capability'), 268 'list of capabilities used to filter courses', 269 VALUE_DEFAULT, array() 270 ), 271 'includenotenrolledcourses' => new external_value(PARAM_BOOL, 'whether to return courses that the user can see 272 even if is not enroled in. This requires the parameter courseids 273 to not be empty.', VALUE_DEFAULT, false) 274 ) 275 ); 276 } 277 278 /** 279 * Returns an array of courses the user is enrolled, and for each course all of the assignments that the user can 280 * view within that course. 281 * 282 * @param array $courseids An optional array of course ids. If provided only assignments within the given course 283 * will be returned. If the user is not enrolled in or can't view a given course a warning will be generated and returned. 284 * @param array $capabilities An array of additional capability checks you wish to be made on the course context. 285 * @param bool $includenotenrolledcourses Wheter to return courses that the user can see even if is not enroled in. 286 * This requires the parameter $courseids to not be empty. 287 * @return An array of courses and warnings. 288 * @since Moodle 2.4 289 */ 290 public static function get_assignments($courseids = array(), $capabilities = array(), $includenotenrolledcourses = false) { 291 global $USER, $DB, $CFG; 292 293 $params = self::validate_parameters( 294 self::get_assignments_parameters(), 295 array( 296 'courseids' => $courseids, 297 'capabilities' => $capabilities, 298 'includenotenrolledcourses' => $includenotenrolledcourses 299 ) 300 ); 301 302 $warnings = array(); 303 $courses = array(); 304 $fields = 'sortorder,shortname,fullname,timemodified'; 305 306 // If the courseids list is empty, we return only the courses where the user is enrolled in. 307 if (empty($params['courseids'])) { 308 $courses = enrol_get_users_courses($USER->id, true, $fields); 309 $courseids = array_keys($courses); 310 } else if ($includenotenrolledcourses) { 311 // In this case, we don't have to check here for enrolmnents. Maybe the user can see the course even if is not enrolled. 312 $courseids = $params['courseids']; 313 } else { 314 // We need to check for enrolments. 315 $mycourses = enrol_get_users_courses($USER->id, true, $fields); 316 $mycourseids = array_keys($mycourses); 317 318 foreach ($params['courseids'] as $courseid) { 319 if (!in_array($courseid, $mycourseids)) { 320 unset($courses[$courseid]); 321 $warnings[] = array( 322 'item' => 'course', 323 'itemid' => $courseid, 324 'warningcode' => '2', 325 'message' => 'User is not enrolled or does not have requested capability' 326 ); 327 } else { 328 $courses[$courseid] = $mycourses[$courseid]; 329 } 330 } 331 $courseids = array_keys($courses); 332 } 333 334 foreach ($courseids as $cid) { 335 336 try { 337 $context = context_course::instance($cid); 338 self::validate_context($context); 339 340 // Check if this course was already loaded (by enrol_get_users_courses). 341 if (!isset($courses[$cid])) { 342 $courses[$cid] = get_course($cid); 343 } 344 $courses[$cid]->contextid = $context->id; 345 } catch (Exception $e) { 346 unset($courses[$cid]); 347 $warnings[] = array( 348 'item' => 'course', 349 'itemid' => $cid, 350 'warningcode' => '1', 351 'message' => 'No access rights in course context '.$e->getMessage() 352 ); 353 continue; 354 } 355 if (count($params['capabilities']) > 0 && !has_all_capabilities($params['capabilities'], $context)) { 356 unset($courses[$cid]); 357 } 358 } 359 $extrafields='m.id as assignmentid, ' . 360 'm.course, ' . 361 'm.nosubmissions, ' . 362 'm.submissiondrafts, ' . 363 'm.sendnotifications, '. 364 'm.sendlatenotifications, ' . 365 'm.sendstudentnotifications, ' . 366 'm.duedate, ' . 367 'm.allowsubmissionsfromdate, '. 368 'm.grade, ' . 369 'm.timemodified, '. 370 'm.completionsubmit, ' . 371 'm.cutoffdate, ' . 372 'm.teamsubmission, ' . 373 'm.requireallteammemberssubmit, '. 374 'm.teamsubmissiongroupingid, ' . 375 'm.blindmarking, ' . 376 'm.revealidentities, ' . 377 'm.attemptreopenmethod, '. 378 'm.maxattempts, ' . 379 'm.markingworkflow, ' . 380 'm.markingallocation, ' . 381 'm.requiresubmissionstatement, '. 382 'm.preventsubmissionnotingroup, '. 383 'm.intro, '. 384 'm.introformat'; 385 $coursearray = array(); 386 foreach ($courses as $id => $course) { 387 $assignmentarray = array(); 388 // Get a list of assignments for the course. 389 if ($modules = get_coursemodules_in_course('assign', $courses[$id]->id, $extrafields)) { 390 foreach ($modules as $module) { 391 $context = context_module::instance($module->id); 392 try { 393 self::validate_context($context); 394 require_capability('mod/assign:view', $context); 395 } catch (Exception $e) { 396 $warnings[] = array( 397 'item' => 'module', 398 'itemid' => $module->id, 399 'warningcode' => '1', 400 'message' => 'No access rights in module context' 401 ); 402 continue; 403 } 404 $configrecords = $DB->get_recordset('assign_plugin_config', array('assignment' => $module->assignmentid)); 405 $configarray = array(); 406 foreach ($configrecords as $configrecord) { 407 $configarray[] = array( 408 'id' => $configrecord->id, 409 'assignment' => $configrecord->assignment, 410 'plugin' => $configrecord->plugin, 411 'subtype' => $configrecord->subtype, 412 'name' => $configrecord->name, 413 'value' => $configrecord->value 414 ); 415 } 416 $configrecords->close(); 417 418 $assignment = array( 419 'id' => $module->assignmentid, 420 'cmid' => $module->id, 421 'course' => $module->course, 422 'name' => $module->name, 423 'nosubmissions' => $module->nosubmissions, 424 'submissiondrafts' => $module->submissiondrafts, 425 'sendnotifications' => $module->sendnotifications, 426 'sendlatenotifications' => $module->sendlatenotifications, 427 'sendstudentnotifications' => $module->sendstudentnotifications, 428 'duedate' => $module->duedate, 429 'allowsubmissionsfromdate' => $module->allowsubmissionsfromdate, 430 'grade' => $module->grade, 431 'timemodified' => $module->timemodified, 432 'completionsubmit' => $module->completionsubmit, 433 'cutoffdate' => $module->cutoffdate, 434 'teamsubmission' => $module->teamsubmission, 435 'requireallteammemberssubmit' => $module->requireallteammemberssubmit, 436 'teamsubmissiongroupingid' => $module->teamsubmissiongroupingid, 437 'blindmarking' => $module->blindmarking, 438 'revealidentities' => $module->revealidentities, 439 'attemptreopenmethod' => $module->attemptreopenmethod, 440 'maxattempts' => $module->maxattempts, 441 'markingworkflow' => $module->markingworkflow, 442 'markingallocation' => $module->markingallocation, 443 'requiresubmissionstatement' => $module->requiresubmissionstatement, 444 'preventsubmissionnotingroup' => $module->preventsubmissionnotingroup, 445 'configs' => $configarray 446 ); 447 448 // Return or not intro and file attachments depending on the plugin settings. 449 $assign = new assign($context, null, null); 450 451 if ($assign->show_intro()) { 452 453 list($assignment['intro'], $assignment['introformat']) = external_format_text($module->intro, 454 $module->introformat, $context->id, 'mod_assign', 'intro', null); 455 $assignment['introfiles'] = external_util::get_area_files($context->id, 'mod_assign', 'intro', false, 456 false); 457 458 $assignment['introattachments'] = external_util::get_area_files($context->id, 'mod_assign', 459 ASSIGN_INTROATTACHMENT_FILEAREA, 0); 460 } 461 462 if ($module->requiresubmissionstatement) { 463 // Submission statement is required, return the submission statement value. 464 $adminconfig = get_config('assign'); 465 list($assignment['submissionstatement'], $assignment['submissionstatementformat']) = external_format_text( 466 $adminconfig->submissionstatement, FORMAT_MOODLE, $context->id, 'mod_assign', '', 0); 467 } 468 469 $assignmentarray[] = $assignment; 470 } 471 } 472 $coursearray[]= array( 473 'id' => $courses[$id]->id, 474 'fullname' => external_format_string($courses[$id]->fullname, $course->contextid), 475 'shortname' => external_format_string($courses[$id]->shortname, $course->contextid), 476 'timemodified' => $courses[$id]->timemodified, 477 'assignments' => $assignmentarray 478 ); 479 } 480 481 $result = array( 482 'courses' => $coursearray, 483 'warnings' => $warnings 484 ); 485 return $result; 486 } 487 488 /** 489 * Creates an assignment external_single_structure 490 * 491 * @return external_single_structure 492 * @since Moodle 2.4 493 */ 494 private static function get_assignments_assignment_structure() { 495 return new external_single_structure( 496 array( 497 'id' => new external_value(PARAM_INT, 'assignment id'), 498 'cmid' => new external_value(PARAM_INT, 'course module id'), 499 'course' => new external_value(PARAM_INT, 'course id'), 500 'name' => new external_value(PARAM_TEXT, 'assignment name'), 501 'nosubmissions' => new external_value(PARAM_INT, 'no submissions'), 502 'submissiondrafts' => new external_value(PARAM_INT, 'submissions drafts'), 503 'sendnotifications' => new external_value(PARAM_INT, 'send notifications'), 504 'sendlatenotifications' => new external_value(PARAM_INT, 'send notifications'), 505 'sendstudentnotifications' => new external_value(PARAM_INT, 'send student notifications (default)'), 506 'duedate' => new external_value(PARAM_INT, 'assignment due date'), 507 'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'allow submissions from date'), 508 'grade' => new external_value(PARAM_INT, 'grade type'), 509 'timemodified' => new external_value(PARAM_INT, 'last time assignment was modified'), 510 'completionsubmit' => new external_value(PARAM_INT, 'if enabled, set activity as complete following submission'), 511 'cutoffdate' => new external_value(PARAM_INT, 'date after which submission is not accepted without an extension'), 512 'teamsubmission' => new external_value(PARAM_INT, 'if enabled, students submit as a team'), 513 'requireallteammemberssubmit' => new external_value(PARAM_INT, 'if enabled, all team members must submit'), 514 'teamsubmissiongroupingid' => new external_value(PARAM_INT, 'the grouping id for the team submission groups'), 515 'blindmarking' => new external_value(PARAM_INT, 'if enabled, hide identities until reveal identities actioned'), 516 'revealidentities' => new external_value(PARAM_INT, 'show identities for a blind marking assignment'), 517 'attemptreopenmethod' => new external_value(PARAM_TEXT, 'method used to control opening new attempts'), 518 'maxattempts' => new external_value(PARAM_INT, 'maximum number of attempts allowed'), 519 'markingworkflow' => new external_value(PARAM_INT, 'enable marking workflow'), 520 'markingallocation' => new external_value(PARAM_INT, 'enable marking allocation'), 521 'requiresubmissionstatement' => new external_value(PARAM_INT, 'student must accept submission statement'), 522 'preventsubmissionnotingroup' => new external_value(PARAM_INT, 'Prevent submission not in group', VALUE_OPTIONAL), 523 'submissionstatement' => new external_value(PARAM_RAW, 'Submission statement formatted.', VALUE_OPTIONAL), 524 'submissionstatementformat' => new external_format_value('submissionstatement', VALUE_OPTIONAL), 525 'configs' => new external_multiple_structure(self::get_assignments_config_structure(), 'configuration settings'), 526 'intro' => new external_value(PARAM_RAW, 527 'assignment intro, not allways returned because it deppends on the activity configuration', VALUE_OPTIONAL), 528 'introformat' => new external_format_value('intro', VALUE_OPTIONAL), 529 'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL), 530 'introattachments' => new external_files('intro attachments files', VALUE_OPTIONAL), 531 ), 'assignment information object'); 532 } 533 534 /** 535 * Creates an assign_plugin_config external_single_structure 536 * 537 * @return external_single_structure 538 * @since Moodle 2.4 539 */ 540 private static function get_assignments_config_structure() { 541 return new external_single_structure( 542 array( 543 'id' => new external_value(PARAM_INT, 'assign_plugin_config id'), 544 'assignment' => new external_value(PARAM_INT, 'assignment id'), 545 'plugin' => new external_value(PARAM_TEXT, 'plugin'), 546 'subtype' => new external_value(PARAM_TEXT, 'subtype'), 547 'name' => new external_value(PARAM_TEXT, 'name'), 548 'value' => new external_value(PARAM_TEXT, 'value') 549 ), 'assignment configuration object' 550 ); 551 } 552 553 /** 554 * Creates a course external_single_structure 555 * 556 * @return external_single_structure 557 * @since Moodle 2.4 558 */ 559 private static function get_assignments_course_structure() { 560 return new external_single_structure( 561 array( 562 'id' => new external_value(PARAM_INT, 'course id'), 563 'fullname' => new external_value(PARAM_TEXT, 'course full name'), 564 'shortname' => new external_value(PARAM_TEXT, 'course short name'), 565 'timemodified' => new external_value(PARAM_INT, 'last time modified'), 566 'assignments' => new external_multiple_structure(self::get_assignments_assignment_structure(), 'assignment info') 567 ), 'course information object' 568 ); 569 } 570 571 /** 572 * Describes the return value for get_assignments 573 * 574 * @return external_single_structure 575 * @since Moodle 2.4 576 */ 577 public static function get_assignments_returns() { 578 return new external_single_structure( 579 array( 580 'courses' => new external_multiple_structure(self::get_assignments_course_structure(), 'list of courses'), 581 'warnings' => new external_warnings('item can be \'course\' (errorcode 1 or 2) or \'module\' (errorcode 1)', 582 'When item is a course then itemid is a course id. When the item is a module then itemid is a module id', 583 'errorcode can be 1 (no access rights) or 2 (not enrolled or no permissions)') 584 ) 585 ); 586 } 587 588 /** 589 * Return information (files and text fields) for the given plugins in the assignment. 590 * 591 * @param assign $assign the assignment object 592 * @param array $assignplugins array of assignment plugins (submission or feedback) 593 * @param stdClass $item the item object (submission or grade) 594 * @return array an array containing the plugins returned information 595 */ 596 private static function get_plugins_data($assign, $assignplugins, $item) { 597 global $CFG; 598 599 $plugins = array(); 600 $fs = get_file_storage(); 601 602 foreach ($assignplugins as $assignplugin) { 603 604 if (!$assignplugin->is_enabled() or !$assignplugin->is_visible()) { 605 continue; 606 } 607 608 $plugin = array( 609 'name' => $assignplugin->get_name(), 610 'type' => $assignplugin->get_type() 611 ); 612 // Subtype is 'assignsubmission', type is currently 'file' or 'onlinetext'. 613 $component = $assignplugin->get_subtype().'_'.$assignplugin->get_type(); 614 615 $fileareas = $assignplugin->get_file_areas(); 616 foreach ($fileareas as $filearea => $name) { 617 $fileareainfo = array('area' => $filearea); 618 619 $fileareainfo['files'] = external_util::get_area_files( 620 $assign->get_context()->id, 621 $component, 622 $filearea, 623 $item->id 624 ); 625 626 $plugin['fileareas'][] = $fileareainfo; 627 } 628 629 $editorfields = $assignplugin->get_editor_fields(); 630 foreach ($editorfields as $name => $description) { 631 $editorfieldinfo = array( 632 'name' => $name, 633 'description' => $description, 634 'text' => $assignplugin->get_editor_text($name, $item->id), 635 'format' => $assignplugin->get_editor_format($name, $item->id) 636 ); 637 $plugin['editorfields'][] = $editorfieldinfo; 638 } 639 $plugins[] = $plugin; 640 } 641 return $plugins; 642 } 643 644 /** 645 * Describes the parameters for get_submissions 646 * 647 * @return external_external_function_parameters 648 * @since Moodle 2.5 649 */ 650 public static function get_submissions_parameters() { 651 return new external_function_parameters( 652 array( 653 'assignmentids' => new external_multiple_structure( 654 new external_value(PARAM_INT, 'assignment id'), 655 '1 or more assignment ids', 656 VALUE_REQUIRED), 657 'status' => new external_value(PARAM_ALPHA, 'status', VALUE_DEFAULT, ''), 658 'since' => new external_value(PARAM_INT, 'submitted since', VALUE_DEFAULT, 0), 659 'before' => new external_value(PARAM_INT, 'submitted before', VALUE_DEFAULT, 0) 660 ) 661 ); 662 } 663 664 /** 665 * Returns submissions for the requested assignment ids 666 * 667 * @param int[] $assignmentids 668 * @param string $status only return submissions with this status 669 * @param int $since only return submissions with timemodified >= since 670 * @param int $before only return submissions with timemodified <= before 671 * @return array of submissions for each requested assignment 672 * @since Moodle 2.5 673 */ 674 public static function get_submissions($assignmentids, $status = '', $since = 0, $before = 0) { 675 global $DB, $CFG; 676 677 $params = self::validate_parameters(self::get_submissions_parameters(), 678 array('assignmentids' => $assignmentids, 679 'status' => $status, 680 'since' => $since, 681 'before' => $before)); 682 683 $warnings = array(); 684 $assignments = array(); 685 686 // Check the user is allowed to get the submissions for the assignments requested. 687 $placeholders = array(); 688 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($params['assignmentids'], SQL_PARAMS_NAMED); 689 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ". 690 "WHERE md.name = :modname AND cm.instance ".$inorequalsql; 691 $placeholders['modname'] = 'assign'; 692 $cms = $DB->get_records_sql($sql, $placeholders); 693 $assigns = array(); 694 foreach ($cms as $cm) { 695 try { 696 $context = context_module::instance($cm->id); 697 self::validate_context($context); 698 require_capability('mod/assign:grade', $context); 699 $assign = new assign($context, null, null); 700 $assigns[] = $assign; 701 } catch (Exception $e) { 702 $warnings[] = array( 703 'item' => 'assignment', 704 'itemid' => $cm->instance, 705 'warningcode' => '1', 706 'message' => 'No access rights in module context' 707 ); 708 } 709 } 710 711 foreach ($assigns as $assign) { 712 $submissions = array(); 713 $placeholders = array('assignid1' => $assign->get_instance()->id, 714 'assignid2' => $assign->get_instance()->id); 715 716 $submissionmaxattempt = 'SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt 717 FROM {assign_submission} mxs 718 WHERE mxs.assignment = :assignid1 GROUP BY mxs.userid'; 719 720 $sql = "SELECT mas.id, mas.assignment,mas.userid,". 721 "mas.timecreated,mas.timemodified,mas.status,mas.groupid,mas.attemptnumber ". 722 "FROM {assign_submission} mas ". 723 "JOIN ( " . $submissionmaxattempt . " ) smx ON mas.userid = smx.userid ". 724 "WHERE mas.assignment = :assignid2 AND mas.attemptnumber = smx.maxattempt"; 725 726 if (!empty($params['status'])) { 727 $placeholders['status'] = $params['status']; 728 $sql = $sql." AND mas.status = :status"; 729 } 730 if (!empty($params['before'])) { 731 $placeholders['since'] = $params['since']; 732 $placeholders['before'] = $params['before']; 733 $sql = $sql." AND mas.timemodified BETWEEN :since AND :before"; 734 } else { 735 $placeholders['since'] = $params['since']; 736 $sql = $sql." AND mas.timemodified >= :since"; 737 } 738 739 $submissionrecords = $DB->get_records_sql($sql, $placeholders); 740 741 if (!empty($submissionrecords)) { 742 $submissionplugins = $assign->get_submission_plugins(); 743 foreach ($submissionrecords as $submissionrecord) { 744 $submission = array( 745 'id' => $submissionrecord->id, 746 'userid' => $submissionrecord->userid, 747 'timecreated' => $submissionrecord->timecreated, 748 'timemodified' => $submissionrecord->timemodified, 749 'status' => $submissionrecord->status, 750 'attemptnumber' => $submissionrecord->attemptnumber, 751 'groupid' => $submissionrecord->groupid, 752 'plugins' => self::get_plugins_data($assign, $submissionplugins, $submissionrecord) 753 ); 754 $submissions[] = $submission; 755 } 756 } else { 757 $warnings[] = array( 758 'item' => 'module', 759 'itemid' => $assign->get_instance()->id, 760 'warningcode' => '3', 761 'message' => 'No submissions found' 762 ); 763 } 764 765 $assignments[] = array( 766 'assignmentid' => $assign->get_instance()->id, 767 'submissions' => $submissions 768 ); 769 770 } 771 772 $result = array( 773 'assignments' => $assignments, 774 'warnings' => $warnings 775 ); 776 return $result; 777 } 778 779 /** 780 * Creates an assignment plugin structure. 781 * 782 * @return external_single_structure the plugin structure 783 */ 784 private static function get_plugin_structure() { 785 return new external_single_structure( 786 array( 787 'type' => new external_value(PARAM_TEXT, 'submission plugin type'), 788 'name' => new external_value(PARAM_TEXT, 'submission plugin name'), 789 'fileareas' => new external_multiple_structure( 790 new external_single_structure( 791 array ( 792 'area' => new external_value (PARAM_TEXT, 'file area'), 793 'files' => new external_files('files', VALUE_OPTIONAL), 794 ) 795 ), 'fileareas', VALUE_OPTIONAL 796 ), 797 'editorfields' => new external_multiple_structure( 798 new external_single_structure( 799 array( 800 'name' => new external_value(PARAM_TEXT, 'field name'), 801 'description' => new external_value(PARAM_TEXT, 'field description'), 802 'text' => new external_value (PARAM_RAW, 'field value'), 803 'format' => new external_format_value ('text') 804 ) 805 ) 806 , 'editorfields', VALUE_OPTIONAL 807 ) 808 ) 809 ); 810 } 811 812 /** 813 * Creates a submission structure. 814 * 815 * @return external_single_structure the submission structure 816 */ 817 private static function get_submission_structure($required = VALUE_REQUIRED) { 818 return new external_single_structure( 819 array( 820 'id' => new external_value(PARAM_INT, 'submission id'), 821 'userid' => new external_value(PARAM_INT, 'student id'), 822 'attemptnumber' => new external_value(PARAM_INT, 'attempt number'), 823 'timecreated' => new external_value(PARAM_INT, 'submission creation time'), 824 'timemodified' => new external_value(PARAM_INT, 'submission last modified time'), 825 'status' => new external_value(PARAM_TEXT, 'submission status'), 826 'groupid' => new external_value(PARAM_INT, 'group id'), 827 'assignment' => new external_value(PARAM_INT, 'assignment id', VALUE_OPTIONAL), 828 'latest' => new external_value(PARAM_INT, 'latest attempt', VALUE_OPTIONAL), 829 'plugins' => new external_multiple_structure(self::get_plugin_structure(), 'plugins', VALUE_OPTIONAL) 830 ), 'submission info', $required 831 ); 832 } 833 834 /** 835 * Creates an assign_submissions external_single_structure 836 * 837 * @return external_single_structure 838 * @since Moodle 2.5 839 */ 840 private static function get_submissions_structure() { 841 return new external_single_structure( 842 array ( 843 'assignmentid' => new external_value(PARAM_INT, 'assignment id'), 844 'submissions' => new external_multiple_structure(self::get_submission_structure()) 845 ) 846 ); 847 } 848 849 /** 850 * Describes the get_submissions return value 851 * 852 * @return external_single_structure 853 * @since Moodle 2.5 854 */ 855 public static function get_submissions_returns() { 856 return new external_single_structure( 857 array( 858 'assignments' => new external_multiple_structure(self::get_submissions_structure(), 'assignment submissions'), 859 'warnings' => new external_warnings() 860 ) 861 ); 862 } 863 864 /** 865 * Describes the parameters for set_user_flags 866 * @return external_function_parameters 867 * @since Moodle 2.6 868 */ 869 public static function set_user_flags_parameters() { 870 return new external_function_parameters( 871 array( 872 'assignmentid' => new external_value(PARAM_INT, 'assignment id'), 873 'userflags' => new external_multiple_structure( 874 new external_single_structure( 875 array( 876 'userid' => new external_value(PARAM_INT, 'student id'), 877 'locked' => new external_value(PARAM_INT, 'locked', VALUE_OPTIONAL), 878 'mailed' => new external_value(PARAM_INT, 'mailed', VALUE_OPTIONAL), 879 'extensionduedate' => new external_value(PARAM_INT, 'extension due date', VALUE_OPTIONAL), 880 'workflowstate' => new external_value(PARAM_TEXT, 'marking workflow state', VALUE_OPTIONAL), 881 'allocatedmarker' => new external_value(PARAM_INT, 'allocated marker', VALUE_OPTIONAL) 882 ) 883 ) 884 ) 885 ) 886 ); 887 } 888 889 /** 890 * Create or update user_flags records 891 * 892 * @param int $assignmentid the assignment for which the userflags are created or updated 893 * @param array $userflags An array of userflags to create or update 894 * @return array containing success or failure information for each record 895 * @since Moodle 2.6 896 */ 897 public static function set_user_flags($assignmentid, $userflags = array()) { 898 global $CFG, $DB; 899 900 $params = self::validate_parameters(self::set_user_flags_parameters(), 901 array('assignmentid' => $assignmentid, 902 'userflags' => $userflags)); 903 904 // Load assignment if it exists and if the user has the capability. 905 list($assign, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 906 require_capability('mod/assign:grade', $context); 907 908 $results = array(); 909 foreach ($params['userflags'] as $userflag) { 910 $success = true; 911 $result = array(); 912 913 $record = $assign->get_user_flags($userflag['userid'], false); 914 if ($record) { 915 if (isset($userflag['locked'])) { 916 $record->locked = $userflag['locked']; 917 } 918 if (isset($userflag['mailed'])) { 919 $record->mailed = $userflag['mailed']; 920 } 921 if (isset($userflag['extensionduedate'])) { 922 $record->extensionduedate = $userflag['extensionduedate']; 923 } 924 if (isset($userflag['workflowstate'])) { 925 $record->workflowstate = $userflag['workflowstate']; 926 } 927 if (isset($userflag['allocatedmarker'])) { 928 $record->allocatedmarker = $userflag['allocatedmarker']; 929 } 930 if ($assign->update_user_flags($record)) { 931 $result['id'] = $record->id; 932 $result['userid'] = $userflag['userid']; 933 } else { 934 $result['id'] = $record->id; 935 $result['userid'] = $userflag['userid']; 936 $result['errormessage'] = 'Record created but values could not be set'; 937 } 938 } else { 939 $record = $assign->get_user_flags($userflag['userid'], true); 940 $setfields = isset($userflag['locked']) 941 || isset($userflag['mailed']) 942 || isset($userflag['extensionduedate']) 943 || isset($userflag['workflowstate']) 944 || isset($userflag['allocatedmarker']); 945 if ($record) { 946 if ($setfields) { 947 if (isset($userflag['locked'])) { 948 $record->locked = $userflag['locked']; 949 } 950 if (isset($userflag['mailed'])) { 951 $record->mailed = $userflag['mailed']; 952 } 953 if (isset($userflag['extensionduedate'])) { 954 $record->extensionduedate = $userflag['extensionduedate']; 955 } 956 if (isset($userflag['workflowstate'])) { 957 $record->workflowstate = $userflag['workflowstate']; 958 } 959 if (isset($userflag['allocatedmarker'])) { 960 $record->allocatedmarker = $userflag['allocatedmarker']; 961 } 962 if ($assign->update_user_flags($record)) { 963 $result['id'] = $record->id; 964 $result['userid'] = $userflag['userid']; 965 } else { 966 $result['id'] = $record->id; 967 $result['userid'] = $userflag['userid']; 968 $result['errormessage'] = 'Record created but values could not be set'; 969 } 970 } else { 971 $result['id'] = $record->id; 972 $result['userid'] = $userflag['userid']; 973 } 974 } else { 975 $result['id'] = -1; 976 $result['userid'] = $userflag['userid']; 977 $result['errormessage'] = 'Record could not be created'; 978 } 979 } 980 981 $results[] = $result; 982 } 983 return $results; 984 } 985 986 /** 987 * Describes the set_user_flags return value 988 * @return external_multiple_structure 989 * @since Moodle 2.6 990 */ 991 public static function set_user_flags_returns() { 992 return new external_multiple_structure( 993 new external_single_structure( 994 array( 995 'id' => new external_value(PARAM_INT, 'id of record if successful, -1 for failure'), 996 'userid' => new external_value(PARAM_INT, 'userid of record'), 997 'errormessage' => new external_value(PARAM_TEXT, 'Failure error message', VALUE_OPTIONAL) 998 ) 999 ) 1000 ); 1001 } 1002 1003 /** 1004 * Describes the parameters for get_user_flags 1005 * @return external_function_parameters 1006 * @since Moodle 2.6 1007 */ 1008 public static function get_user_flags_parameters() { 1009 return new external_function_parameters( 1010 array( 1011 'assignmentids' => new external_multiple_structure( 1012 new external_value(PARAM_INT, 'assignment id'), 1013 '1 or more assignment ids', 1014 VALUE_REQUIRED) 1015 ) 1016 ); 1017 } 1018 1019 /** 1020 * Returns user flag information from assign_user_flags for the requested assignment ids 1021 * @param int[] $assignmentids 1022 * @return array of user flag records for each requested assignment 1023 * @since Moodle 2.6 1024 */ 1025 public static function get_user_flags($assignmentids) { 1026 global $DB; 1027 $params = self::validate_parameters(self::get_user_flags_parameters(), 1028 array('assignmentids' => $assignmentids)); 1029 1030 $assignments = array(); 1031 $warnings = array(); 1032 $requestedassignmentids = $params['assignmentids']; 1033 1034 // Check the user is allowed to get the user flags for the assignments requested. 1035 $placeholders = array(); 1036 list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED); 1037 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ". 1038 "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids; 1039 $placeholders['modname'] = 'assign'; 1040 $cms = $DB->get_records_sql($sql, $placeholders); 1041 foreach ($cms as $cm) { 1042 try { 1043 $context = context_module::instance($cm->id); 1044 self::validate_context($context); 1045 require_capability('mod/assign:grade', $context); 1046 } catch (Exception $e) { 1047 $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance)); 1048 $warning = array(); 1049 $warning['item'] = 'assignment'; 1050 $warning['itemid'] = $cm->instance; 1051 $warning['warningcode'] = '1'; 1052 $warning['message'] = 'No access rights in module context'; 1053 $warnings[] = $warning; 1054 } 1055 } 1056 1057 // Create the query and populate an array of assign_user_flags records from the recordset results. 1058 if (count ($requestedassignmentids) > 0) { 1059 $placeholders = array(); 1060 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED); 1061 1062 $sql = "SELECT auf.id,auf.assignment,auf.userid,auf.locked,auf.mailed,". 1063 "auf.extensionduedate,auf.workflowstate,auf.allocatedmarker ". 1064 "FROM {assign_user_flags} auf ". 1065 "WHERE auf.assignment ".$inorequalsql. 1066 " ORDER BY auf.assignment, auf.id"; 1067 1068 $rs = $DB->get_recordset_sql($sql, $placeholders); 1069 $currentassignmentid = null; 1070 $assignment = null; 1071 foreach ($rs as $rd) { 1072 $userflag = array(); 1073 $userflag['id'] = $rd->id; 1074 $userflag['userid'] = $rd->userid; 1075 $userflag['locked'] = $rd->locked; 1076 $userflag['mailed'] = $rd->mailed; 1077 $userflag['extensionduedate'] = $rd->extensionduedate; 1078 $userflag['workflowstate'] = $rd->workflowstate; 1079 $userflag['allocatedmarker'] = $rd->allocatedmarker; 1080 1081 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) { 1082 if (!is_null($assignment)) { 1083 $assignments[] = $assignment; 1084 } 1085 $assignment = array(); 1086 $assignment['assignmentid'] = $rd->assignment; 1087 $assignment['userflags'] = array(); 1088 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment)); 1089 } 1090 $assignment['userflags'][] = $userflag; 1091 1092 $currentassignmentid = $rd->assignment; 1093 } 1094 if (!is_null($assignment)) { 1095 $assignments[] = $assignment; 1096 } 1097 $rs->close(); 1098 1099 } 1100 1101 foreach ($requestedassignmentids as $assignmentid) { 1102 $warning = array(); 1103 $warning['item'] = 'assignment'; 1104 $warning['itemid'] = $assignmentid; 1105 $warning['warningcode'] = '3'; 1106 $warning['message'] = 'No user flags found'; 1107 $warnings[] = $warning; 1108 } 1109 1110 $result = array(); 1111 $result['assignments'] = $assignments; 1112 $result['warnings'] = $warnings; 1113 return $result; 1114 } 1115 1116 /** 1117 * Creates an assign_user_flags external_single_structure 1118 * @return external_single_structure 1119 * @since Moodle 2.6 1120 */ 1121 private static function assign_user_flags() { 1122 return new external_single_structure( 1123 array ( 1124 'assignmentid' => new external_value(PARAM_INT, 'assignment id'), 1125 'userflags' => new external_multiple_structure(new external_single_structure( 1126 array( 1127 'id' => new external_value(PARAM_INT, 'user flag id'), 1128 'userid' => new external_value(PARAM_INT, 'student id'), 1129 'locked' => new external_value(PARAM_INT, 'locked'), 1130 'mailed' => new external_value(PARAM_INT, 'mailed'), 1131 'extensionduedate' => new external_value(PARAM_INT, 'extension due date'), 1132 'workflowstate' => new external_value(PARAM_TEXT, 'marking workflow state', VALUE_OPTIONAL), 1133 'allocatedmarker' => new external_value(PARAM_INT, 'allocated marker') 1134 ) 1135 ) 1136 ) 1137 ) 1138 ); 1139 } 1140 1141 /** 1142 * Describes the get_user_flags return value 1143 * @return external_single_structure 1144 * @since Moodle 2.6 1145 */ 1146 public static function get_user_flags_returns() { 1147 return new external_single_structure( 1148 array( 1149 'assignments' => new external_multiple_structure(self::assign_user_flags(), 'list of assign user flag information'), 1150 'warnings' => new external_warnings('item is always \'assignment\'', 1151 'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module id', 1152 'errorcode can be 3 (no user flags found) or 1 (no permission to get user flags)') 1153 ) 1154 ); 1155 } 1156 1157 /** 1158 * Describes the parameters for get_user_mappings 1159 * @return external_function_parameters 1160 * @since Moodle 2.6 1161 */ 1162 public static function get_user_mappings_parameters() { 1163 return new external_function_parameters( 1164 array( 1165 'assignmentids' => new external_multiple_structure( 1166 new external_value(PARAM_INT, 'assignment id'), 1167 '1 or more assignment ids', 1168 VALUE_REQUIRED) 1169 ) 1170 ); 1171 } 1172 1173 /** 1174 * Returns user mapping information from assign_user_mapping for the requested assignment ids 1175 * @param int[] $assignmentids 1176 * @return array of user mapping records for each requested assignment 1177 * @since Moodle 2.6 1178 */ 1179 public static function get_user_mappings($assignmentids) { 1180 global $DB; 1181 $params = self::validate_parameters(self::get_user_mappings_parameters(), 1182 array('assignmentids' => $assignmentids)); 1183 1184 $assignments = array(); 1185 $warnings = array(); 1186 $requestedassignmentids = $params['assignmentids']; 1187 1188 // Check the user is allowed to get the mappings for the assignments requested. 1189 $placeholders = array(); 1190 list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED); 1191 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ". 1192 "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids; 1193 $placeholders['modname'] = 'assign'; 1194 $cms = $DB->get_records_sql($sql, $placeholders); 1195 foreach ($cms as $cm) { 1196 try { 1197 $context = context_module::instance($cm->id); 1198 self::validate_context($context); 1199 require_capability('mod/assign:revealidentities', $context); 1200 } catch (Exception $e) { 1201 $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance)); 1202 $warning = array(); 1203 $warning['item'] = 'assignment'; 1204 $warning['itemid'] = $cm->instance; 1205 $warning['warningcode'] = '1'; 1206 $warning['message'] = 'No access rights in module context'; 1207 $warnings[] = $warning; 1208 } 1209 } 1210 1211 // Create the query and populate an array of assign_user_mapping records from the recordset results. 1212 if (count ($requestedassignmentids) > 0) { 1213 $placeholders = array(); 1214 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED); 1215 1216 $sql = "SELECT aum.id,aum.assignment,aum.userid ". 1217 "FROM {assign_user_mapping} aum ". 1218 "WHERE aum.assignment ".$inorequalsql. 1219 " ORDER BY aum.assignment, aum.id"; 1220 1221 $rs = $DB->get_recordset_sql($sql, $placeholders); 1222 $currentassignmentid = null; 1223 $assignment = null; 1224 foreach ($rs as $rd) { 1225 $mapping = array(); 1226 $mapping['id'] = $rd->id; 1227 $mapping['userid'] = $rd->userid; 1228 1229 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) { 1230 if (!is_null($assignment)) { 1231 $assignments[] = $assignment; 1232 } 1233 $assignment = array(); 1234 $assignment['assignmentid'] = $rd->assignment; 1235 $assignment['mappings'] = array(); 1236 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment)); 1237 } 1238 $assignment['mappings'][] = $mapping; 1239 1240 $currentassignmentid = $rd->assignment; 1241 } 1242 if (!is_null($assignment)) { 1243 $assignments[] = $assignment; 1244 } 1245 $rs->close(); 1246 1247 } 1248 1249 foreach ($requestedassignmentids as $assignmentid) { 1250 $warning = array(); 1251 $warning['item'] = 'assignment'; 1252 $warning['itemid'] = $assignmentid; 1253 $warning['warningcode'] = '3'; 1254 $warning['message'] = 'No mappings found'; 1255 $warnings[] = $warning; 1256 } 1257 1258 $result = array(); 1259 $result['assignments'] = $assignments; 1260 $result['warnings'] = $warnings; 1261 return $result; 1262 } 1263 1264 /** 1265 * Creates an assign_user_mappings external_single_structure 1266 * @return external_single_structure 1267 * @since Moodle 2.6 1268 */ 1269 private static function assign_user_mappings() { 1270 return new external_single_structure( 1271 array ( 1272 'assignmentid' => new external_value(PARAM_INT, 'assignment id'), 1273 'mappings' => new external_multiple_structure(new external_single_structure( 1274 array( 1275 'id' => new external_value(PARAM_INT, 'user mapping id'), 1276 'userid' => new external_value(PARAM_INT, 'student id') 1277 ) 1278 ) 1279 ) 1280 ) 1281 ); 1282 } 1283 1284 /** 1285 * Describes the get_user_mappings return value 1286 * @return external_single_structure 1287 * @since Moodle 2.6 1288 */ 1289 public static function get_user_mappings_returns() { 1290 return new external_single_structure( 1291 array( 1292 'assignments' => new external_multiple_structure(self::assign_user_mappings(), 'list of assign user mapping data'), 1293 'warnings' => new external_warnings('item is always \'assignment\'', 1294 'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module id', 1295 'errorcode can be 3 (no user mappings found) or 1 (no permission to get user mappings)') 1296 ) 1297 ); 1298 } 1299 1300 /** 1301 * Describes the parameters for lock_submissions 1302 * @return external_external_function_parameters 1303 * @since Moodle 2.6 1304 */ 1305 public static function lock_submissions_parameters() { 1306 return new external_function_parameters( 1307 array( 1308 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1309 'userids' => new external_multiple_structure( 1310 new external_value(PARAM_INT, 'user id'), 1311 '1 or more user ids', 1312 VALUE_REQUIRED), 1313 ) 1314 ); 1315 } 1316 1317 /** 1318 * Locks (prevent updates to) submissions in this assignment. 1319 * 1320 * @param int $assignmentid The id of the assignment 1321 * @param array $userids Array of user ids to lock 1322 * @return array of warnings for each submission that could not be locked. 1323 * @since Moodle 2.6 1324 */ 1325 public static function lock_submissions($assignmentid, $userids) { 1326 global $CFG; 1327 1328 $params = self::validate_parameters(self::lock_submissions_parameters(), 1329 array('assignmentid' => $assignmentid, 1330 'userids' => $userids)); 1331 1332 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1333 1334 $warnings = array(); 1335 foreach ($params['userids'] as $userid) { 1336 if (!$assignment->lock_submission($userid)) { 1337 $detail = 'User id: ' . $userid . ', Assignment id: ' . $params['assignmentid']; 1338 $warnings[] = self::generate_warning($params['assignmentid'], 1339 'couldnotlock', 1340 $detail); 1341 } 1342 } 1343 1344 return $warnings; 1345 } 1346 1347 /** 1348 * Describes the return value for lock_submissions 1349 * 1350 * @return external_single_structure 1351 * @since Moodle 2.6 1352 */ 1353 public static function lock_submissions_returns() { 1354 return new external_warnings(); 1355 } 1356 1357 /** 1358 * Describes the parameters for revert_submissions_to_draft 1359 * @return external_external_function_parameters 1360 * @since Moodle 2.6 1361 */ 1362 public static function revert_submissions_to_draft_parameters() { 1363 return new external_function_parameters( 1364 array( 1365 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1366 'userids' => new external_multiple_structure( 1367 new external_value(PARAM_INT, 'user id'), 1368 '1 or more user ids', 1369 VALUE_REQUIRED), 1370 ) 1371 ); 1372 } 1373 1374 /** 1375 * Reverts a list of user submissions to draft for a single assignment. 1376 * 1377 * @param int $assignmentid The id of the assignment 1378 * @param array $userids Array of user ids to revert 1379 * @return array of warnings for each submission that could not be reverted. 1380 * @since Moodle 2.6 1381 */ 1382 public static function revert_submissions_to_draft($assignmentid, $userids) { 1383 global $CFG; 1384 1385 $params = self::validate_parameters(self::revert_submissions_to_draft_parameters(), 1386 array('assignmentid' => $assignmentid, 1387 'userids' => $userids)); 1388 1389 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1390 1391 $warnings = array(); 1392 foreach ($params['userids'] as $userid) { 1393 if (!$assignment->revert_to_draft($userid)) { 1394 $detail = 'User id: ' . $userid . ', Assignment id: ' . $params['assignmentid']; 1395 $warnings[] = self::generate_warning($params['assignmentid'], 1396 'couldnotrevert', 1397 $detail); 1398 } 1399 } 1400 1401 return $warnings; 1402 } 1403 1404 /** 1405 * Describes the return value for revert_submissions_to_draft 1406 * 1407 * @return external_single_structure 1408 * @since Moodle 2.6 1409 */ 1410 public static function revert_submissions_to_draft_returns() { 1411 return new external_warnings(); 1412 } 1413 1414 /** 1415 * Describes the parameters for unlock_submissions 1416 * @return external_external_function_parameters 1417 * @since Moodle 2.6 1418 */ 1419 public static function unlock_submissions_parameters() { 1420 return new external_function_parameters( 1421 array( 1422 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1423 'userids' => new external_multiple_structure( 1424 new external_value(PARAM_INT, 'user id'), 1425 '1 or more user ids', 1426 VALUE_REQUIRED), 1427 ) 1428 ); 1429 } 1430 1431 /** 1432 * Locks (prevent updates to) submissions in this assignment. 1433 * 1434 * @param int $assignmentid The id of the assignment 1435 * @param array $userids Array of user ids to lock 1436 * @return array of warnings for each submission that could not be locked. 1437 * @since Moodle 2.6 1438 */ 1439 public static function unlock_submissions($assignmentid, $userids) { 1440 global $CFG; 1441 1442 $params = self::validate_parameters(self::unlock_submissions_parameters(), 1443 array('assignmentid' => $assignmentid, 1444 'userids' => $userids)); 1445 1446 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1447 1448 $warnings = array(); 1449 foreach ($params['userids'] as $userid) { 1450 if (!$assignment->unlock_submission($userid)) { 1451 $detail = 'User id: ' . $userid . ', Assignment id: ' . $params['assignmentid']; 1452 $warnings[] = self::generate_warning($params['assignmentid'], 1453 'couldnotunlock', 1454 $detail); 1455 } 1456 } 1457 1458 return $warnings; 1459 } 1460 1461 /** 1462 * Describes the return value for unlock_submissions 1463 * 1464 * @return external_single_structure 1465 * @since Moodle 2.6 1466 */ 1467 public static function unlock_submissions_returns() { 1468 return new external_warnings(); 1469 } 1470 1471 /** 1472 * Describes the parameters for submit_grading_form webservice. 1473 * @return external_external_function_parameters 1474 * @since Moodle 3.1 1475 */ 1476 public static function submit_grading_form_parameters() { 1477 return new external_function_parameters( 1478 array( 1479 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1480 'userid' => new external_value(PARAM_INT, 'The user id the submission belongs to'), 1481 'jsonformdata' => new external_value(PARAM_RAW, 'The data from the grading form, encoded as a json array') 1482 ) 1483 ); 1484 } 1485 1486 /** 1487 * Submit the logged in users assignment for grading. 1488 * 1489 * @param int $assignmentid The id of the assignment 1490 * @param int $userid The id of the user the submission belongs to. 1491 * @param string $jsonformdata The data from the form, encoded as a json array. 1492 * @return array of warnings to indicate any errors. 1493 * @since Moodle 2.6 1494 */ 1495 public static function submit_grading_form($assignmentid, $userid, $jsonformdata) { 1496 global $CFG, $USER; 1497 1498 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 1499 require_once($CFG->dirroot . '/mod/assign/gradeform.php'); 1500 1501 $params = self::validate_parameters(self::submit_grading_form_parameters(), 1502 array( 1503 'assignmentid' => $assignmentid, 1504 'userid' => $userid, 1505 'jsonformdata' => $jsonformdata 1506 )); 1507 1508 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1509 1510 $serialiseddata = json_decode($params['jsonformdata']); 1511 1512 $data = array(); 1513 parse_str($serialiseddata, $data); 1514 1515 $warnings = array(); 1516 1517 $options = array( 1518 'userid' => $params['userid'], 1519 'attemptnumber' => $data['attemptnumber'], 1520 'rownum' => 0, 1521 'gradingpanel' => true 1522 ); 1523 1524 $customdata = (object) $data; 1525 $formparams = array($assignment, $customdata, $options); 1526 1527 // Data is injected into the form by the last param for the constructor. 1528 $mform = new mod_assign_grade_form(null, $formparams, 'post', '', null, true, $data); 1529 $validateddata = $mform->get_data(); 1530 1531 if ($validateddata) { 1532 $assignment->save_grade($params['userid'], $validateddata); 1533 } else { 1534 $warnings[] = self::generate_warning($params['assignmentid'], 1535 'couldnotsavegrade', 1536 'Form validation failed.'); 1537 } 1538 1539 1540 return $warnings; 1541 } 1542 1543 /** 1544 * Describes the return for submit_grading_form 1545 * @return external_external_function_parameters 1546 * @since Moodle 3.1 1547 */ 1548 public static function submit_grading_form_returns() { 1549 return new external_warnings(); 1550 } 1551 1552 /** 1553 * Describes the parameters for submit_for_grading 1554 * @return external_external_function_parameters 1555 * @since Moodle 2.6 1556 */ 1557 public static function submit_for_grading_parameters() { 1558 return new external_function_parameters( 1559 array( 1560 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1561 'acceptsubmissionstatement' => new external_value(PARAM_BOOL, 'Accept the assignment submission statement') 1562 ) 1563 ); 1564 } 1565 1566 /** 1567 * Submit the logged in users assignment for grading. 1568 * 1569 * @param int $assignmentid The id of the assignment 1570 * @return array of warnings to indicate any errors. 1571 * @since Moodle 2.6 1572 */ 1573 public static function submit_for_grading($assignmentid, $acceptsubmissionstatement) { 1574 global $CFG, $USER; 1575 1576 $params = self::validate_parameters(self::submit_for_grading_parameters(), 1577 array('assignmentid' => $assignmentid, 1578 'acceptsubmissionstatement' => $acceptsubmissionstatement)); 1579 1580 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1581 1582 $warnings = array(); 1583 $data = new stdClass(); 1584 $data->submissionstatement = $params['acceptsubmissionstatement']; 1585 $notices = array(); 1586 1587 if (!$assignment->submit_for_grading($data, $notices)) { 1588 $detail = 'User id: ' . $USER->id . ', Assignment id: ' . $params['assignmentid'] . ' Notices:' . implode(', ', $notices); 1589 $warnings[] = self::generate_warning($params['assignmentid'], 1590 'couldnotsubmitforgrading', 1591 $detail); 1592 } 1593 1594 return $warnings; 1595 } 1596 1597 /** 1598 * Describes the return value for submit_for_grading 1599 * 1600 * @return external_single_structure 1601 * @since Moodle 2.6 1602 */ 1603 public static function submit_for_grading_returns() { 1604 return new external_warnings(); 1605 } 1606 1607 /** 1608 * Describes the parameters for save_user_extensions 1609 * @return external_external_function_parameters 1610 * @since Moodle 2.6 1611 */ 1612 public static function save_user_extensions_parameters() { 1613 return new external_function_parameters( 1614 array( 1615 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1616 'userids' => new external_multiple_structure( 1617 new external_value(PARAM_INT, 'user id'), 1618 '1 or more user ids', 1619 VALUE_REQUIRED), 1620 'dates' => new external_multiple_structure( 1621 new external_value(PARAM_INT, 'dates'), 1622 '1 or more extension dates (timestamp)', 1623 VALUE_REQUIRED), 1624 ) 1625 ); 1626 } 1627 1628 /** 1629 * Grant extension dates to students for an assignment. 1630 * 1631 * @param int $assignmentid The id of the assignment 1632 * @param array $userids Array of user ids to grant extensions to 1633 * @param array $dates Array of extension dates 1634 * @return array of warnings for each extension date that could not be granted 1635 * @since Moodle 2.6 1636 */ 1637 public static function save_user_extensions($assignmentid, $userids, $dates) { 1638 global $CFG; 1639 1640 $params = self::validate_parameters(self::save_user_extensions_parameters(), 1641 array('assignmentid' => $assignmentid, 1642 'userids' => $userids, 1643 'dates' => $dates)); 1644 1645 if (count($params['userids']) != count($params['dates'])) { 1646 $detail = 'Length of userids and dates parameters differ.'; 1647 $warnings[] = self::generate_warning($params['assignmentid'], 1648 'invalidparameters', 1649 $detail); 1650 1651 return $warnings; 1652 } 1653 1654 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1655 1656 $warnings = array(); 1657 foreach ($params['userids'] as $idx => $userid) { 1658 $duedate = $params['dates'][$idx]; 1659 if (!$assignment->save_user_extension($userid, $duedate)) { 1660 $detail = 'User id: ' . $userid . ', Assignment id: ' . $params['assignmentid'] . ', Extension date: ' . $duedate; 1661 $warnings[] = self::generate_warning($params['assignmentid'], 1662 'couldnotgrantextensions', 1663 $detail); 1664 } 1665 } 1666 1667 return $warnings; 1668 } 1669 1670 /** 1671 * Describes the return value for save_user_extensions 1672 * 1673 * @return external_single_structure 1674 * @since Moodle 2.6 1675 */ 1676 public static function save_user_extensions_returns() { 1677 return new external_warnings(); 1678 } 1679 1680 /** 1681 * Describes the parameters for reveal_identities 1682 * @return external_external_function_parameters 1683 * @since Moodle 2.6 1684 */ 1685 public static function reveal_identities_parameters() { 1686 return new external_function_parameters( 1687 array( 1688 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on') 1689 ) 1690 ); 1691 } 1692 1693 /** 1694 * Reveal the identities of anonymous students to markers for a single assignment. 1695 * 1696 * @param int $assignmentid The id of the assignment 1697 * @return array of warnings to indicate any errors. 1698 * @since Moodle 2.6 1699 */ 1700 public static function reveal_identities($assignmentid) { 1701 global $CFG, $USER; 1702 1703 $params = self::validate_parameters(self::reveal_identities_parameters(), 1704 array('assignmentid' => $assignmentid)); 1705 1706 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1707 1708 $warnings = array(); 1709 if (!$assignment->reveal_identities()) { 1710 $detail = 'User id: ' . $USER->id . ', Assignment id: ' . $params['assignmentid']; 1711 $warnings[] = self::generate_warning($params['assignmentid'], 1712 'couldnotrevealidentities', 1713 $detail); 1714 } 1715 1716 return $warnings; 1717 } 1718 1719 /** 1720 * Describes the return value for reveal_identities 1721 * 1722 * @return external_single_structure 1723 * @since Moodle 2.6 1724 */ 1725 public static function reveal_identities_returns() { 1726 return new external_warnings(); 1727 } 1728 1729 /** 1730 * Describes the parameters for save_submission 1731 * @return external_external_function_parameters 1732 * @since Moodle 2.6 1733 */ 1734 public static function save_submission_parameters() { 1735 global $CFG; 1736 $instance = new assign(null, null, null); 1737 $pluginsubmissionparams = array(); 1738 1739 foreach ($instance->get_submission_plugins() as $plugin) { 1740 if ($plugin->is_visible()) { 1741 $pluginparams = $plugin->get_external_parameters(); 1742 if (!empty($pluginparams)) { 1743 $pluginsubmissionparams = array_merge($pluginsubmissionparams, $pluginparams); 1744 } 1745 } 1746 } 1747 1748 return new external_function_parameters( 1749 array( 1750 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1751 'plugindata' => new external_single_structure( 1752 $pluginsubmissionparams 1753 ) 1754 ) 1755 ); 1756 } 1757 1758 /** 1759 * Save a student submission for a single assignment 1760 * 1761 * @param int $assignmentid The id of the assignment 1762 * @param array $plugindata - The submitted data for plugins 1763 * @return array of warnings to indicate any errors 1764 * @since Moodle 2.6 1765 */ 1766 public static function save_submission($assignmentid, $plugindata) { 1767 global $CFG, $USER; 1768 1769 $params = self::validate_parameters(self::save_submission_parameters(), 1770 array('assignmentid' => $assignmentid, 1771 'plugindata' => $plugindata)); 1772 1773 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1774 1775 $notices = array(); 1776 1777 if (!$assignment->submissions_open($USER->id)) { 1778 $notices[] = get_string('duedatereached', 'assign'); 1779 } else { 1780 $submissiondata = (object)$params['plugindata']; 1781 $assignment->save_submission($submissiondata, $notices); 1782 } 1783 1784 $warnings = array(); 1785 foreach ($notices as $notice) { 1786 $warnings[] = self::generate_warning($params['assignmentid'], 1787 'couldnotsavesubmission', 1788 $notice); 1789 } 1790 1791 return $warnings; 1792 } 1793 1794 /** 1795 * Describes the return value for save_submission 1796 * 1797 * @return external_single_structure 1798 * @since Moodle 2.6 1799 */ 1800 public static function save_submission_returns() { 1801 return new external_warnings(); 1802 } 1803 1804 /** 1805 * Describes the parameters for save_grade 1806 * @return external_external_function_parameters 1807 * @since Moodle 2.6 1808 */ 1809 public static function save_grade_parameters() { 1810 global $CFG; 1811 require_once("$CFG->dirroot/grade/grading/lib.php"); 1812 $instance = new assign(null, null, null); 1813 $pluginfeedbackparams = array(); 1814 1815 foreach ($instance->get_feedback_plugins() as $plugin) { 1816 if ($plugin->is_visible()) { 1817 $pluginparams = $plugin->get_external_parameters(); 1818 if (!empty($pluginparams)) { 1819 $pluginfeedbackparams = array_merge($pluginfeedbackparams, $pluginparams); 1820 } 1821 } 1822 } 1823 1824 $advancedgradingdata = array(); 1825 $methods = array_keys(grading_manager::available_methods(false)); 1826 foreach ($methods as $method) { 1827 require_once($CFG->dirroot.'/grade/grading/form/'.$method.'/lib.php'); 1828 $details = call_user_func('gradingform_'.$method.'_controller::get_external_instance_filling_details'); 1829 if (!empty($details)) { 1830 $items = array(); 1831 foreach ($details as $key => $value) { 1832 $value->required = VALUE_OPTIONAL; 1833 unset($value->content->keys['id']); 1834 $items[$key] = new external_multiple_structure (new external_single_structure( 1835 array( 1836 'criterionid' => new external_value(PARAM_INT, 'criterion id'), 1837 'fillings' => $value 1838 ) 1839 )); 1840 } 1841 $advancedgradingdata[$method] = new external_single_structure($items, 'items', VALUE_OPTIONAL); 1842 } 1843 } 1844 1845 return new external_function_parameters( 1846 array( 1847 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1848 'userid' => new external_value(PARAM_INT, 'The student id to operate on'), 1849 'grade' => new external_value(PARAM_FLOAT, 'The new grade for this user. Ignored if advanced grading used'), 1850 'attemptnumber' => new external_value(PARAM_INT, 'The attempt number (-1 means latest attempt)'), 1851 'addattempt' => new external_value(PARAM_BOOL, 'Allow another attempt if the attempt reopen method is manual'), 1852 'workflowstate' => new external_value(PARAM_ALPHA, 'The next marking workflow state'), 1853 'applytoall' => new external_value(PARAM_BOOL, 'If true, this grade will be applied ' . 1854 'to all members ' . 1855 'of the group (for group assignments).'), 1856 'plugindata' => new external_single_structure($pluginfeedbackparams, 'plugin data', VALUE_DEFAULT, array()), 1857 'advancedgradingdata' => new external_single_structure($advancedgradingdata, 'advanced grading data', 1858 VALUE_DEFAULT, array()) 1859 ) 1860 ); 1861 } 1862 1863 /** 1864 * Save a student grade for a single assignment. 1865 * 1866 * @param int $assignmentid The id of the assignment 1867 * @param int $userid The id of the user 1868 * @param float $grade The grade (ignored if the assignment uses advanced grading) 1869 * @param int $attemptnumber The attempt number 1870 * @param bool $addattempt Allow another attempt 1871 * @param string $workflowstate New workflow state 1872 * @param bool $applytoall Apply the grade to all members of the group 1873 * @param array $plugindata Custom data used by plugins 1874 * @param array $advancedgradingdata Advanced grading data 1875 * @return null 1876 * @since Moodle 2.6 1877 */ 1878 public static function save_grade($assignmentid, 1879 $userid, 1880 $grade, 1881 $attemptnumber, 1882 $addattempt, 1883 $workflowstate, 1884 $applytoall, 1885 $plugindata = array(), 1886 $advancedgradingdata = array()) { 1887 global $CFG, $USER; 1888 1889 $params = self::validate_parameters(self::save_grade_parameters(), 1890 array('assignmentid' => $assignmentid, 1891 'userid' => $userid, 1892 'grade' => $grade, 1893 'attemptnumber' => $attemptnumber, 1894 'workflowstate' => $workflowstate, 1895 'addattempt' => $addattempt, 1896 'applytoall' => $applytoall, 1897 'plugindata' => $plugindata, 1898 'advancedgradingdata' => $advancedgradingdata)); 1899 1900 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 1901 1902 $gradedata = (object)$params['plugindata']; 1903 1904 $gradedata->addattempt = $params['addattempt']; 1905 $gradedata->attemptnumber = $params['attemptnumber']; 1906 $gradedata->workflowstate = $params['workflowstate']; 1907 $gradedata->applytoall = $params['applytoall']; 1908 $gradedata->grade = $params['grade']; 1909 1910 if (!empty($params['advancedgradingdata'])) { 1911 $advancedgrading = array(); 1912 $criteria = reset($params['advancedgradingdata']); 1913 foreach ($criteria as $key => $criterion) { 1914 $details = array(); 1915 foreach ($criterion as $value) { 1916 foreach ($value['fillings'] as $filling) { 1917 $details[$value['criterionid']] = $filling; 1918 } 1919 } 1920 $advancedgrading[$key] = $details; 1921 } 1922 $gradedata->advancedgrading = $advancedgrading; 1923 } 1924 1925 $assignment->save_grade($params['userid'], $gradedata); 1926 1927 return null; 1928 } 1929 1930 /** 1931 * Describes the return value for save_grade 1932 * 1933 * @return external_single_structure 1934 * @since Moodle 2.6 1935 */ 1936 public static function save_grade_returns() { 1937 return null; 1938 } 1939 1940 /** 1941 * Describes the parameters for save_grades 1942 * @return external_external_function_parameters 1943 * @since Moodle 2.7 1944 */ 1945 public static function save_grades_parameters() { 1946 global $CFG; 1947 require_once("$CFG->dirroot/grade/grading/lib.php"); 1948 $instance = new assign(null, null, null); 1949 $pluginfeedbackparams = array(); 1950 1951 foreach ($instance->get_feedback_plugins() as $plugin) { 1952 if ($plugin->is_visible()) { 1953 $pluginparams = $plugin->get_external_parameters(); 1954 if (!empty($pluginparams)) { 1955 $pluginfeedbackparams = array_merge($pluginfeedbackparams, $pluginparams); 1956 } 1957 } 1958 } 1959 1960 $advancedgradingdata = array(); 1961 $methods = array_keys(grading_manager::available_methods(false)); 1962 foreach ($methods as $method) { 1963 require_once($CFG->dirroot.'/grade/grading/form/'.$method.'/lib.php'); 1964 $details = call_user_func('gradingform_'.$method.'_controller::get_external_instance_filling_details'); 1965 if (!empty($details)) { 1966 $items = array(); 1967 foreach ($details as $key => $value) { 1968 $value->required = VALUE_OPTIONAL; 1969 unset($value->content->keys['id']); 1970 $items[$key] = new external_multiple_structure (new external_single_structure( 1971 array( 1972 'criterionid' => new external_value(PARAM_INT, 'criterion id'), 1973 'fillings' => $value 1974 ) 1975 )); 1976 } 1977 $advancedgradingdata[$method] = new external_single_structure($items, 'items', VALUE_OPTIONAL); 1978 } 1979 } 1980 1981 return new external_function_parameters( 1982 array( 1983 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 1984 'applytoall' => new external_value(PARAM_BOOL, 'If true, this grade will be applied ' . 1985 'to all members ' . 1986 'of the group (for group assignments).'), 1987 'grades' => new external_multiple_structure( 1988 new external_single_structure( 1989 array ( 1990 'userid' => new external_value(PARAM_INT, 'The student id to operate on'), 1991 'grade' => new external_value(PARAM_FLOAT, 'The new grade for this user. '. 1992 'Ignored if advanced grading used'), 1993 'attemptnumber' => new external_value(PARAM_INT, 'The attempt number (-1 means latest attempt)'), 1994 'addattempt' => new external_value(PARAM_BOOL, 'Allow another attempt if manual attempt reopen method'), 1995 'workflowstate' => new external_value(PARAM_ALPHA, 'The next marking workflow state'), 1996 'plugindata' => new external_single_structure($pluginfeedbackparams, 'plugin data', 1997 VALUE_DEFAULT, array()), 1998 'advancedgradingdata' => new external_single_structure($advancedgradingdata, 'advanced grading data', 1999 VALUE_DEFAULT, array()) 2000 ) 2001 ) 2002 ) 2003 ) 2004 ); 2005 } 2006 2007 /** 2008 * Save multiple student grades for a single assignment. 2009 * 2010 * @param int $assignmentid The id of the assignment 2011 * @param boolean $applytoall If set to true and this is a team assignment, 2012 * apply the grade to all members of the group 2013 * @param array $grades grade data for one or more students that includes 2014 * userid - The id of the student being graded 2015 * grade - The grade (ignored if the assignment uses advanced grading) 2016 * attemptnumber - The attempt number 2017 * addattempt - Allow another attempt 2018 * workflowstate - New workflow state 2019 * plugindata - Custom data used by plugins 2020 * advancedgradingdata - Optional Advanced grading data 2021 * @throws invalid_parameter_exception if multiple grades are supplied for 2022 * a team assignment that has $applytoall set to true 2023 * @return null 2024 * @since Moodle 2.7 2025 */ 2026 public static function save_grades($assignmentid, $applytoall = false, $grades) { 2027 global $CFG, $USER; 2028 2029 $params = self::validate_parameters(self::save_grades_parameters(), 2030 array('assignmentid' => $assignmentid, 2031 'applytoall' => $applytoall, 2032 'grades' => $grades)); 2033 2034 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 2035 2036 if ($assignment->get_instance()->teamsubmission && $params['applytoall']) { 2037 // Check that only 1 user per submission group is provided. 2038 $groupids = array(); 2039 foreach ($params['grades'] as $gradeinfo) { 2040 $group = $assignment->get_submission_group($gradeinfo['userid']); 2041 if (in_array($group->id, $groupids)) { 2042 throw new invalid_parameter_exception('Multiple grades for the same team have been supplied ' 2043 .' this is not permitted when the applytoall flag is set'); 2044 } else { 2045 $groupids[] = $group->id; 2046 } 2047 } 2048 } 2049 2050 foreach ($params['grades'] as $gradeinfo) { 2051 $gradedata = (object)$gradeinfo['plugindata']; 2052 $gradedata->addattempt = $gradeinfo['addattempt']; 2053 $gradedata->attemptnumber = $gradeinfo['attemptnumber']; 2054 $gradedata->workflowstate = $gradeinfo['workflowstate']; 2055 $gradedata->applytoall = $params['applytoall']; 2056 $gradedata->grade = $gradeinfo['grade']; 2057 2058 if (!empty($gradeinfo['advancedgradingdata'])) { 2059 $advancedgrading = array(); 2060 $criteria = reset($gradeinfo['advancedgradingdata']); 2061 foreach ($criteria as $key => $criterion) { 2062 $details = array(); 2063 foreach ($criterion as $value) { 2064 foreach ($value['fillings'] as $filling) { 2065 $details[$value['criterionid']] = $filling; 2066 } 2067 } 2068 $advancedgrading[$key] = $details; 2069 } 2070 $gradedata->advancedgrading = $advancedgrading; 2071 } 2072 $assignment->save_grade($gradeinfo['userid'], $gradedata); 2073 } 2074 2075 return null; 2076 } 2077 2078 /** 2079 * Describes the return value for save_grades 2080 * 2081 * @return external_single_structure 2082 * @since Moodle 2.7 2083 */ 2084 public static function save_grades_returns() { 2085 return null; 2086 } 2087 2088 /** 2089 * Describes the parameters for copy_previous_attempt 2090 * @return external_function_parameters 2091 * @since Moodle 2.6 2092 */ 2093 public static function copy_previous_attempt_parameters() { 2094 return new external_function_parameters( 2095 array( 2096 'assignmentid' => new external_value(PARAM_INT, 'The assignment id to operate on'), 2097 ) 2098 ); 2099 } 2100 2101 /** 2102 * Copy a students previous attempt to a new attempt. 2103 * 2104 * @param int $assignmentid 2105 * @return array of warnings to indicate any errors. 2106 * @since Moodle 2.6 2107 */ 2108 public static function copy_previous_attempt($assignmentid) { 2109 2110 $params = self::validate_parameters(self::copy_previous_attempt_parameters(), 2111 array('assignmentid' => $assignmentid)); 2112 2113 list($assignment, $course, $cm, $context) = self::validate_assign($params['assignmentid']); 2114 2115 $notices = array(); 2116 2117 $assignment->copy_previous_attempt($notices); 2118 2119 $warnings = array(); 2120 foreach ($notices as $notice) { 2121 $warnings[] = self::generate_warning($assignmentid, 2122 'couldnotcopyprevioussubmission', 2123 $notice); 2124 } 2125 2126 return $warnings; 2127 } 2128 2129 /** 2130 * Describes the return value for save_submission 2131 * 2132 * @return external_single_structure 2133 * @since Moodle 2.6 2134 */ 2135 public static function copy_previous_attempt_returns() { 2136 return new external_warnings(); 2137 } 2138 2139 /** 2140 * Returns description of method parameters 2141 * 2142 * @return external_function_parameters 2143 * @since Moodle 3.0 2144 */ 2145 public static function view_grading_table_parameters() { 2146 return new external_function_parameters( 2147 array( 2148 'assignid' => new external_value(PARAM_INT, 'assign instance id') 2149 ) 2150 ); 2151 } 2152 2153 /** 2154 * Trigger the grading_table_viewed event. 2155 * 2156 * @param int $assignid the assign instance id 2157 * @return array of warnings and status result 2158 * @since Moodle 3.0 2159 * @throws moodle_exception 2160 */ 2161 public static function view_grading_table($assignid) { 2162 2163 $params = self::validate_parameters(self::view_grading_table_parameters(), 2164 array( 2165 'assignid' => $assignid 2166 )); 2167 $warnings = array(); 2168 2169 list($assign, $course, $cm, $context) = self::validate_assign($params['assignid']); 2170 2171 $assign->require_view_grades(); 2172 \mod_assign\event\grading_table_viewed::create_from_assign($assign)->trigger(); 2173 2174 $result = array(); 2175 $result['status'] = true; 2176 $result['warnings'] = $warnings; 2177 return $result; 2178 } 2179 2180 /** 2181 * Returns description of method result value 2182 * 2183 * @return external_description 2184 * @since Moodle 3.0 2185 */ 2186 public static function view_grading_table_returns() { 2187 return new external_single_structure( 2188 array( 2189 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 2190 'warnings' => new external_warnings() 2191 ) 2192 ); 2193 } 2194 2195 /** 2196 * Describes the parameters for view_submission_status. 2197 * 2198 * @return external_external_function_parameters 2199 * @since Moodle 3.1 2200 */ 2201 public static function view_submission_status_parameters() { 2202 return new external_function_parameters ( 2203 array( 2204 'assignid' => new external_value(PARAM_INT, 'assign instance id'), 2205 ) 2206 ); 2207 } 2208 2209 /** 2210 * Trigger the submission status viewed event. 2211 * 2212 * @param int $assignid assign instance id 2213 * @return array of warnings and status result 2214 * @since Moodle 3.1 2215 */ 2216 public static function view_submission_status($assignid) { 2217 2218 $warnings = array(); 2219 $params = array( 2220 'assignid' => $assignid, 2221 ); 2222 $params = self::validate_parameters(self::view_submission_status_parameters(), $params); 2223 2224 list($assign, $course, $cm, $context) = self::validate_assign($params['assignid']); 2225 2226 \mod_assign\event\submission_status_viewed::create_from_assign($assign)->trigger(); 2227 2228 $result = array(); 2229 $result['status'] = true; 2230 $result['warnings'] = $warnings; 2231 return $result; 2232 } 2233 2234 /** 2235 * Describes the view_submission_status return value. 2236 * 2237 * @return external_single_structure 2238 * @since Moodle 3.1 2239 */ 2240 public static function view_submission_status_returns() { 2241 return new external_single_structure( 2242 array( 2243 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 2244 'warnings' => new external_warnings(), 2245 ) 2246 ); 2247 } 2248 2249 /** 2250 * Describes the parameters for get_submission_status. 2251 * 2252 * @return external_external_function_parameters 2253 * @since Moodle 3.1 2254 */ 2255 public static function get_submission_status_parameters() { 2256 return new external_function_parameters ( 2257 array( 2258 'assignid' => new external_value(PARAM_INT, 'assignment instance id'), 2259 'userid' => new external_value(PARAM_INT, 'user id (empty for current user)', VALUE_DEFAULT, 0), 2260 ) 2261 ); 2262 } 2263 2264 /** 2265 * Returns information about an assignment submission status for a given user. 2266 * 2267 * @param int $assignid assignment instance id 2268 * @param int $userid user id (empty for current user) 2269 * @return array of warnings and grading, status, feedback and previous attempts information 2270 * @since Moodle 3.1 2271 * @throws required_capability_exception 2272 */ 2273 public static function get_submission_status($assignid, $userid = 0) { 2274 global $USER; 2275 2276 $warnings = array(); 2277 2278 $params = array( 2279 'assignid' => $assignid, 2280 'userid' => $userid, 2281 ); 2282 $params = self::validate_parameters(self::get_submission_status_parameters(), $params); 2283 2284 list($assign, $course, $cm, $context) = self::validate_assign($params['assignid']); 2285 2286 // Default value for userid. 2287 if (empty($params['userid'])) { 2288 $params['userid'] = $USER->id; 2289 } 2290 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 2291 core_user::require_active_user($user); 2292 2293 if (!$assign->can_view_submission($user->id)) { 2294 throw new required_capability_exception($context, 'mod/assign:viewgrades', 'nopermission', ''); 2295 } 2296 2297 $gradingsummary = $lastattempt = $feedback = $previousattempts = null; 2298 2299 // Get the renderable since it contais all the info we need. 2300 if ($assign->can_view_grades()) { 2301 $gradingsummary = $assign->get_assign_grading_summary_renderable(); 2302 } 2303 2304 // Retrieve the rest of the renderable objects. 2305 if (has_capability('mod/assign:submit', $assign->get_context(), $user)) { 2306 $lastattempt = $assign->get_assign_submission_status_renderable($user, true); 2307 } 2308 2309 $feedback = $assign->get_assign_feedback_status_renderable($user); 2310 2311 $previousattempts = $assign->get_assign_attempt_history_renderable($user); 2312 2313 // Now, build the result. 2314 $result = array(); 2315 2316 // First of all, grading summary, this is suitable for teachers/managers. 2317 if ($gradingsummary) { 2318 $result['gradingsummary'] = $gradingsummary; 2319 } 2320 2321 // Did we submit anything? 2322 if ($lastattempt) { 2323 $submissionplugins = $assign->get_submission_plugins(); 2324 2325 if (empty($lastattempt->submission)) { 2326 unset($lastattempt->submission); 2327 } else { 2328 $lastattempt->submission->plugins = self::get_plugins_data($assign, $submissionplugins, $lastattempt->submission); 2329 } 2330 2331 if (empty($lastattempt->teamsubmission)) { 2332 unset($lastattempt->teamsubmission); 2333 } else { 2334 $lastattempt->teamsubmission->plugins = self::get_plugins_data($assign, $submissionplugins, 2335 $lastattempt->teamsubmission); 2336 } 2337 2338 // We need to change the type of some of the structures retrieved from the renderable. 2339 if (!empty($lastattempt->submissiongroup)) { 2340 $lastattempt->submissiongroup = $lastattempt->submissiongroup->id; 2341 } else { 2342 unset($lastattempt->submissiongroup); 2343 } 2344 2345 if (!empty($lastattempt->usergroups)) { 2346 $lastattempt->usergroups = array_keys($lastattempt->usergroups); 2347 } 2348 // We cannot use array_keys here. 2349 if (!empty($lastattempt->submissiongroupmemberswhoneedtosubmit)) { 2350 $lastattempt->submissiongroupmemberswhoneedtosubmit = array_map( 2351 function($e){ 2352 return $e->id; 2353 }, 2354 $lastattempt->submissiongroupmemberswhoneedtosubmit); 2355 } 2356 2357 $result['lastattempt'] = $lastattempt; 2358 } 2359 2360 // The feedback for our latest submission. 2361 if ($feedback) { 2362 if ($feedback->grade) { 2363 $feedbackplugins = $assign->get_feedback_plugins(); 2364 $feedback->plugins = self::get_plugins_data($assign, $feedbackplugins, $feedback->grade); 2365 } else { 2366 unset($feedback->plugins); 2367 unset($feedback->grade); 2368 } 2369 2370 $result['feedback'] = $feedback; 2371 } 2372 2373 // Retrieve only previous attempts. 2374 if ($previousattempts and count($previousattempts->submissions) > 1) { 2375 // Don't show the last one because it is the current submission. 2376 array_pop($previousattempts->submissions); 2377 2378 // Show newest to oldest. 2379 $previousattempts->submissions = array_reverse($previousattempts->submissions); 2380 2381 foreach ($previousattempts->submissions as $i => $submission) { 2382 $attempt = array(); 2383 2384 $grade = null; 2385 foreach ($previousattempts->grades as $onegrade) { 2386 if ($onegrade->attemptnumber == $submission->attemptnumber) { 2387 $grade = $onegrade; 2388 break; 2389 } 2390 } 2391 2392 $attempt['attemptnumber'] = $submission->attemptnumber; 2393 2394 if ($submission) { 2395 $submission->plugins = self::get_plugins_data($assign, $previousattempts->submissionplugins, $submission); 2396 $attempt['submission'] = $submission; 2397 } 2398 2399 if ($grade) { 2400 // From object to id. 2401 $grade->grader = $grade->grader->id; 2402 $feedbackplugins = self::get_plugins_data($assign, $previousattempts->feedbackplugins, $grade); 2403 2404 $attempt['grade'] = $grade; 2405 $attempt['feedbackplugins'] = $feedbackplugins; 2406 } 2407 $result['previousattempts'][] = $attempt; 2408 } 2409 } 2410 2411 $result['warnings'] = $warnings; 2412 return $result; 2413 } 2414 2415 /** 2416 * Describes the get_submission_status return value. 2417 * 2418 * @return external_single_structure 2419 * @since Moodle 3.1 2420 */ 2421 public static function get_submission_status_returns() { 2422 return new external_single_structure( 2423 array( 2424 'gradingsummary' => new external_single_structure( 2425 array( 2426 'participantcount' => new external_value(PARAM_INT, 'Number of users who can submit.'), 2427 'submissiondraftscount' => new external_value(PARAM_INT, 'Number of submissions in draft status.'), 2428 'submissiondraftscount' => new external_value(PARAM_INT, 'Number of submissions in draft status.'), 2429 'submissionsenabled' => new external_value(PARAM_BOOL, 'Whether submissions are enabled or not.'), 2430 'submissionssubmittedcount' => new external_value(PARAM_INT, 'Number of submissions in submitted status.'), 2431 'submissionsneedgradingcount' => new external_value(PARAM_INT, 'Number of submissions that need grading.'), 2432 'warnofungroupedusers' => new external_value(PARAM_BOOL, 'Whether we need to warn people that there 2433 are users without groups.'), 2434 ), 'Grading information.', VALUE_OPTIONAL 2435 ), 2436 'lastattempt' => new external_single_structure( 2437 array( 2438 'submission' => self::get_submission_structure(VALUE_OPTIONAL), 2439 'teamsubmission' => self::get_submission_structure(VALUE_OPTIONAL), 2440 'submissiongroup' => new external_value(PARAM_INT, 'The submission group id (for group submissions only).', 2441 VALUE_OPTIONAL), 2442 'submissiongroupmemberswhoneedtosubmit' => new external_multiple_structure( 2443 new external_value(PARAM_INT, 'USER id.'), 2444 'List of users who still need to submit (for group submissions only).', 2445 VALUE_OPTIONAL 2446 ), 2447 'submissionsenabled' => new external_value(PARAM_BOOL, 'Whether submissions are enabled or not.'), 2448 'locked' => new external_value(PARAM_BOOL, 'Whether new submissions are locked.'), 2449 'graded' => new external_value(PARAM_BOOL, 'Whether the submission is graded.'), 2450 'canedit' => new external_value(PARAM_BOOL, 'Whether the user can edit the current submission.'), 2451 'cansubmit' => new external_value(PARAM_BOOL, 'Whether the user can submit.'), 2452 'extensionduedate' => new external_value(PARAM_INT, 'Extension due date.'), 2453 'blindmarking' => new external_value(PARAM_BOOL, 'Whether blind marking is enabled.'), 2454 'gradingstatus' => new external_value(PARAM_ALPHANUMEXT, 'Grading status.'), 2455 'usergroups' => new external_multiple_structure( 2456 new external_value(PARAM_INT, 'Group id.'), 'User groups in the course.' 2457 ), 2458 ), 'Last attempt information.', VALUE_OPTIONAL 2459 ), 2460 'feedback' => new external_single_structure( 2461 array( 2462 'grade' => self::get_grade_structure(VALUE_OPTIONAL), 2463 'gradefordisplay' => new external_value(PARAM_RAW, 'Grade rendered into a format suitable for display.'), 2464 'gradeddate' => new external_value(PARAM_INT, 'The date the user was graded.'), 2465 'plugins' => new external_multiple_structure(self::get_plugin_structure(), 'Plugins info.', VALUE_OPTIONAL), 2466 ), 'Feedback for the last attempt.', VALUE_OPTIONAL 2467 ), 2468 'previousattempts' => new external_multiple_structure( 2469 new external_single_structure( 2470 array( 2471 'attemptnumber' => new external_value(PARAM_INT, 'Attempt number.'), 2472 'submission' => self::get_submission_structure(VALUE_OPTIONAL), 2473 'grade' => self::get_grade_structure(VALUE_OPTIONAL), 2474 'feedbackplugins' => new external_multiple_structure(self::get_plugin_structure(), 'Feedback info.', 2475 VALUE_OPTIONAL), 2476 ) 2477 ), 'List all the previous attempts did by the user.', VALUE_OPTIONAL 2478 ), 2479 'warnings' => new external_warnings(), 2480 ) 2481 ); 2482 } 2483 2484 /** 2485 * Returns description of method parameters 2486 * 2487 * @return external_function_parameters 2488 * @since Moodle 3.1 2489 */ 2490 public static function list_participants_parameters() { 2491 return new external_function_parameters( 2492 array( 2493 'assignid' => new external_value(PARAM_INT, 'assign instance id'), 2494 'groupid' => new external_value(PARAM_INT, 'group id'), 2495 'filter' => new external_value(PARAM_RAW, 'search string to filter the results'), 2496 'skip' => new external_value(PARAM_INT, 'number of records to skip', VALUE_DEFAULT, 0), 2497 'limit' => new external_value(PARAM_INT, 'maximum number of records to return', VALUE_DEFAULT, 0), 2498 'onlyids' => new external_value(PARAM_BOOL, 'Do not return all user fields', VALUE_DEFAULT, false), 2499 ) 2500 ); 2501 } 2502 2503 /** 2504 * Retrieves the list of students to be graded for the assignment. 2505 * 2506 * @param int $assignid the assign instance id 2507 * @param int $groupid the current group id 2508 * @param string $filter search string to filter the results. 2509 * @param int $skip Number of records to skip 2510 * @param int $limit Maximum number of records to return 2511 * @param bool $onlyids Only return user ids. 2512 * @return array of warnings and status result 2513 * @since Moodle 3.1 2514 * @throws moodle_exception 2515 */ 2516 public static function list_participants($assignid, $groupid, $filter, $skip, $limit, $onlyids) { 2517 global $DB, $CFG; 2518 require_once($CFG->dirroot . "/mod/assign/locallib.php"); 2519 require_once($CFG->dirroot . "/user/lib.php"); 2520 2521 $params = self::validate_parameters(self::list_participants_parameters(), 2522 array( 2523 'assignid' => $assignid, 2524 'groupid' => $groupid, 2525 'filter' => $filter, 2526 'skip' => $skip, 2527 'limit' => $limit, 2528 'onlyids' => $onlyids 2529 )); 2530 $warnings = array(); 2531 2532 list($assign, $course, $cm, $context) = self::validate_assign($params['assignid']); 2533 2534 require_capability('mod/assign:view', $context); 2535 2536 $assign->require_view_grades(); 2537 2538 $participants = $assign->list_participants_with_filter_status_and_group($params['groupid']); 2539 2540 $result = array(); 2541 $index = 0; 2542 foreach ($participants as $record) { 2543 // Preserve the fullname set by the assignment. 2544 $fullname = $record->fullname; 2545 $searchable = $fullname; 2546 $match = false; 2547 if (empty($filter)) { 2548 $match = true; 2549 } else { 2550 $filter = core_text::strtolower($filter); 2551 $value = core_text::strtolower($searchable); 2552 if (is_string($value) && (core_text::strpos($value, $filter) !== false)) { 2553 $match = true; 2554 } 2555 } 2556 if ($match) { 2557 $index++; 2558 if ($index <= $params['skip']) { 2559 continue; 2560 } 2561 if (($params['limit'] > 0) && (($index - $params['skip']) > $params['limit'])) { 2562 break; 2563 } 2564 // Now we do the expensive lookup of user details because we completed the filtering. 2565 if (!$assign->is_blind_marking() && !$params['onlyids']) { 2566 $userdetails = user_get_user_details($record, $course); 2567 } else { 2568 $userdetails = array('id' => $record->id); 2569 } 2570 $userdetails['fullname'] = $fullname; 2571 $userdetails['submitted'] = $record->submitted; 2572 $userdetails['requiregrading'] = $record->requiregrading; 2573 if (!empty($record->groupid)) { 2574 $userdetails['groupid'] = $record->groupid; 2575 } 2576 if (!empty($record->groupname)) { 2577 $userdetails['groupname'] = $record->groupname; 2578 } 2579 2580 $result[] = $userdetails; 2581 } 2582 } 2583 return $result; 2584 } 2585 2586 /** 2587 * Returns the description of the results of the mod_assign_external::list_participants() method. 2588 * 2589 * @return external_description 2590 * @since Moodle 3.1 2591 */ 2592 public static function list_participants_returns() { 2593 // Get user description. 2594 $userdesc = core_user_external::user_description(); 2595 // List unneeded properties. 2596 $unneededproperties = [ 2597 'auth', 'confirmed', 'lang', 'calendartype', 'theme', 'timezone', 'mailformat' 2598 ]; 2599 // Remove unneeded properties for consistency with the previous version. 2600 foreach ($unneededproperties as $prop) { 2601 unset($userdesc->keys[$prop]); 2602 } 2603 2604 // Override property attributes for consistency with the previous version. 2605 $userdesc->keys['fullname']->type = PARAM_NOTAGS; 2606 $userdesc->keys['profileimageurlsmall']->required = VALUE_OPTIONAL; 2607 $userdesc->keys['profileimageurl']->required = VALUE_OPTIONAL; 2608 $userdesc->keys['email']->desc = 'Email address'; 2609 $userdesc->keys['email']->desc = 'Email address'; 2610 $userdesc->keys['idnumber']->desc = 'The idnumber of the user'; 2611 2612 // Define other keys. 2613 $otherkeys = [ 2614 'groups' => new external_multiple_structure( 2615 new external_single_structure( 2616 [ 2617 'id' => new external_value(PARAM_INT, 'group id'), 2618 'name' => new external_value(PARAM_RAW, 'group name'), 2619 'description' => new external_value(PARAM_RAW, 'group description'), 2620 ] 2621 ), 'user groups', VALUE_OPTIONAL 2622 ), 2623 'roles' => new external_multiple_structure( 2624 new external_single_structure( 2625 [ 2626 'roleid' => new external_value(PARAM_INT, 'role id'), 2627 'name' => new external_value(PARAM_RAW, 'role name'), 2628 'shortname' => new external_value(PARAM_ALPHANUMEXT, 'role shortname'), 2629 'sortorder' => new external_value(PARAM_INT, 'role sortorder') 2630 ] 2631 ), 'user roles', VALUE_OPTIONAL 2632 ), 2633 'enrolledcourses' => new external_multiple_structure( 2634 new external_single_structure( 2635 [ 2636 'id' => new external_value(PARAM_INT, 'Id of the course'), 2637 'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'), 2638 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course') 2639 ] 2640 ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL 2641 ), 2642 'submitted' => new external_value(PARAM_BOOL, 'have they submitted their assignment'), 2643 'requiregrading' => new external_value(PARAM_BOOL, 'is their submission waiting for grading'), 2644 'groupid' => new external_value(PARAM_INT, 'for group assignments this is the group id', VALUE_OPTIONAL), 2645 'groupname' => new external_value(PARAM_NOTAGS, 'for group assignments this is the group name', VALUE_OPTIONAL), 2646 ]; 2647 2648 // Merge keys. 2649 $userdesc->keys = array_merge($userdesc->keys, $otherkeys); 2650 return new external_multiple_structure($userdesc); 2651 } 2652 2653 /** 2654 * Returns description of method parameters 2655 * 2656 * @return external_function_parameters 2657 * @since Moodle 3.1 2658 */ 2659 public static function get_participant_parameters() { 2660 return new external_function_parameters( 2661 array( 2662 'assignid' => new external_value(PARAM_INT, 'assign instance id'), 2663 'userid' => new external_value(PARAM_INT, 'user id'), 2664 'embeduser' => new external_value(PARAM_BOOL, 'user id', VALUE_DEFAULT, false), 2665 ) 2666 ); 2667 } 2668 2669 /** 2670 * Get the user participating in the given assignment. An error with code 'usernotincourse' 2671 * is thrown is the user isn't a participant of the given assignment. 2672 * 2673 * @param int $assignid the assign instance id 2674 * @param int $userid the user id 2675 * @param bool $embeduser return user details (only applicable if not blind marking) 2676 * @return array of warnings and status result 2677 * @since Moodle 3.1 2678 * @throws moodle_exception 2679 */ 2680 public static function get_participant($assignid, $userid, $embeduser) { 2681 global $DB, $CFG; 2682 require_once($CFG->dirroot . "/mod/assign/locallib.php"); 2683 require_once($CFG->dirroot . "/user/lib.php"); 2684 2685 $params = self::validate_parameters(self::get_participant_parameters(), array( 2686 'assignid' => $assignid, 2687 'userid' => $userid, 2688 'embeduser' => $embeduser 2689 )); 2690 2691 list($assign, $course, $cm, $context) = self::validate_assign($params['assignid']); 2692 $assign->require_view_grades(); 2693 2694 $participant = $assign->get_participant($params['userid']); 2695 if (!$participant) { 2696 // No participant found so we can return early. 2697 throw new moodle_exception('usernotincourse'); 2698 } 2699 2700 $return = array( 2701 'id' => $participant->id, 2702 'fullname' => $participant->fullname, 2703 'submitted' => $participant->submitted, 2704 'requiregrading' => $participant->requiregrading, 2705 'blindmarking' => $assign->is_blind_marking(), 2706 ); 2707 2708 if (!empty($participant->groupid)) { 2709 $return['groupid'] = $participant->groupid; 2710 } 2711 if (!empty($participant->groupname)) { 2712 $return['groupname'] = $participant->groupname; 2713 } 2714 2715 // Skip the expensive lookup of user detail if we're blind marking or the caller 2716 // hasn't asked for user details to be embedded. 2717 if (!$assign->is_blind_marking() && $embeduser) { 2718 $return['user'] = user_get_user_details($participant, $course); 2719 } 2720 2721 return $return; 2722 } 2723 2724 /** 2725 * Returns description of method result value 2726 * 2727 * @return external_description 2728 * @since Moodle 3.1 2729 */ 2730 public static function get_participant_returns() { 2731 $userdescription = core_user_external::user_description(); 2732 $userdescription->default = []; 2733 $userdescription->required = VALUE_OPTIONAL; 2734 2735 return new external_single_structure(array( 2736 'id' => new external_value(PARAM_INT, 'ID of the user'), 2737 'fullname' => new external_value(PARAM_NOTAGS, 'The fullname of the user'), 2738 'submitted' => new external_value(PARAM_BOOL, 'have they submitted their assignment'), 2739 'requiregrading' => new external_value(PARAM_BOOL, 'is their submission waiting for grading'), 2740 'blindmarking' => new external_value(PARAM_BOOL, 'is blind marking enabled for this assignment'), 2741 'groupid' => new external_value(PARAM_INT, 'for group assignments this is the group id', VALUE_OPTIONAL), 2742 'groupname' => new external_value(PARAM_NOTAGS, 'for group assignments this is the group name', VALUE_OPTIONAL), 2743 'user' => $userdescription, 2744 )); 2745 } 2746 2747 /** 2748 * Utility function for validating an assign. 2749 * 2750 * @param int $assignid assign instance id 2751 * @return array array containing the assign, course, context and course module objects 2752 * @since Moodle 3.2 2753 */ 2754 protected static function validate_assign($assignid) { 2755 global $DB; 2756 2757 // Request and permission validation. 2758 $assign = $DB->get_record('assign', array('id' => $assignid), 'id', MUST_EXIST); 2759 list($course, $cm) = get_course_and_cm_from_instance($assign, 'assign'); 2760 2761 $context = context_module::instance($cm->id); 2762 // Please, note that is not required to check mod/assign:view because is done by validate_context->require_login. 2763 self::validate_context($context); 2764 $assign = new assign($context, $cm, $course); 2765 2766 return array($assign, $course, $cm, $context); 2767 } 2768 2769 /** 2770 * Describes the parameters for view_assign. 2771 * 2772 * @return external_external_function_parameters 2773 * @since Moodle 3.2 2774 */ 2775 public static function view_assign_parameters() { 2776 return new external_function_parameters ( 2777 array( 2778 'assignid' => new external_value(PARAM_INT, 'assign instance id'), 2779 ) 2780 ); 2781 } 2782 2783 /** 2784 * Update the module completion status. 2785 * 2786 * @param int $assignid assign instance id 2787 * @return array of warnings and status result 2788 * @since Moodle 3.2 2789 */ 2790 public static function view_assign($assignid) { 2791 $warnings = array(); 2792 $params = array( 2793 'assignid' => $assignid, 2794 ); 2795 $params = self::validate_parameters(self::view_assign_parameters(), $params); 2796 2797 list($assign, $course, $cm, $context) = self::validate_assign($params['assignid']); 2798 2799 $assign->set_module_viewed(); 2800 2801 $result = array(); 2802 $result['status'] = true; 2803 $result['warnings'] = $warnings; 2804 return $result; 2805 } 2806 2807 /** 2808 * Describes the view_assign return value. 2809 * 2810 * @return external_single_structure 2811 * @since Moodle 3.2 2812 */ 2813 public static function view_assign_returns() { 2814 return new external_single_structure( 2815 array( 2816 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 2817 'warnings' => new external_warnings(), 2818 ) 2819 ); 2820 } 2821 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |