[ Index ] |
PHP Cross Reference of moodle-2.8 |
[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 * This file contains the moodle hooks for the assign module. 19 * 20 * It delegates most functions to the assignment class. 21 * 22 * @package mod_assign 23 * @copyright 2012 NetSpot {@link http://www.netspot.com.au} 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Adds an assignment instance 30 * 31 * This is done by calling the add_instance() method of the assignment type class 32 * @param stdClass $data 33 * @param mod_assign_mod_form $form 34 * @return int The instance id of the new assignment 35 */ 36 function assign_add_instance(stdClass $data, mod_assign_mod_form $form = null) { 37 global $CFG; 38 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 39 40 $assignment = new assign(context_module::instance($data->coursemodule), null, null); 41 return $assignment->add_instance($data, true); 42 } 43 44 /** 45 * delete an assignment instance 46 * @param int $id 47 * @return bool 48 */ 49 function assign_delete_instance($id) { 50 global $CFG; 51 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 52 $cm = get_coursemodule_from_instance('assign', $id, 0, false, MUST_EXIST); 53 $context = context_module::instance($cm->id); 54 55 $assignment = new assign($context, null, null); 56 return $assignment->delete_instance(); 57 } 58 59 /** 60 * This function is used by the reset_course_userdata function in moodlelib. 61 * This function will remove all assignment submissions and feedbacks in the database 62 * and clean up any related data. 63 * 64 * @param stdClass $data the data submitted from the reset course. 65 * @return array 66 */ 67 function assign_reset_userdata($data) { 68 global $CFG, $DB; 69 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 70 71 $status = array(); 72 $params = array('courseid'=>$data->courseid); 73 $sql = "SELECT a.id FROM {assign} a WHERE a.course=:courseid"; 74 $course = $DB->get_record('course', array('id'=>$data->courseid), '*', MUST_EXIST); 75 if ($assigns = $DB->get_records_sql($sql, $params)) { 76 foreach ($assigns as $assign) { 77 $cm = get_coursemodule_from_instance('assign', 78 $assign->id, 79 $data->courseid, 80 false, 81 MUST_EXIST); 82 $context = context_module::instance($cm->id); 83 $assignment = new assign($context, $cm, $course); 84 $status = array_merge($status, $assignment->reset_userdata($data)); 85 } 86 } 87 return $status; 88 } 89 90 /** 91 * Removes all grades from gradebook 92 * 93 * @param int $courseid The ID of the course to reset 94 * @param string $type Optional type of assignment to limit the reset to a particular assignment type 95 */ 96 function assign_reset_gradebook($courseid, $type='') { 97 global $CFG, $DB; 98 99 $params = array('moduletype'=>'assign', 'courseid'=>$courseid); 100 $sql = 'SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid 101 FROM {assign} a, {course_modules} cm, {modules} m 102 WHERE m.name=:moduletype AND m.id=cm.module AND cm.instance=a.id AND a.course=:courseid'; 103 104 if ($assignments = $DB->get_records_sql($sql, $params)) { 105 foreach ($assignments as $assignment) { 106 assign_grade_item_update($assignment, 'reset'); 107 } 108 } 109 } 110 111 /** 112 * Implementation of the function for printing the form elements that control 113 * whether the course reset functionality affects the assignment. 114 * @param moodleform $mform form passed by reference 115 */ 116 function assign_reset_course_form_definition(&$mform) { 117 $mform->addElement('header', 'assignheader', get_string('modulenameplural', 'assign')); 118 $name = get_string('deleteallsubmissions', 'assign'); 119 $mform->addElement('advcheckbox', 'reset_assign_submissions', $name); 120 } 121 122 /** 123 * Course reset form defaults. 124 * @param object $course 125 * @return array 126 */ 127 function assign_reset_course_form_defaults($course) { 128 return array('reset_assign_submissions'=>1); 129 } 130 131 /** 132 * Update an assignment instance 133 * 134 * This is done by calling the update_instance() method of the assignment type class 135 * @param stdClass $data 136 * @param stdClass $form - unused 137 * @return object 138 */ 139 function assign_update_instance(stdClass $data, $form) { 140 global $CFG; 141 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 142 $context = context_module::instance($data->coursemodule); 143 $assignment = new assign($context, null, null); 144 return $assignment->update_instance($data); 145 } 146 147 /** 148 * Return the list if Moodle features this module supports 149 * 150 * @param string $feature FEATURE_xx constant for requested feature 151 * @return mixed True if module supports feature, null if doesn't know 152 */ 153 function assign_supports($feature) { 154 switch($feature) { 155 case FEATURE_GROUPS: 156 return true; 157 case FEATURE_GROUPINGS: 158 return true; 159 case FEATURE_MOD_INTRO: 160 return true; 161 case FEATURE_COMPLETION_TRACKS_VIEWS: 162 return true; 163 case FEATURE_COMPLETION_HAS_RULES: 164 return true; 165 case FEATURE_GRADE_HAS_GRADE: 166 return true; 167 case FEATURE_GRADE_OUTCOMES: 168 return true; 169 case FEATURE_BACKUP_MOODLE2: 170 return true; 171 case FEATURE_SHOW_DESCRIPTION: 172 return true; 173 case FEATURE_ADVANCED_GRADING: 174 return true; 175 case FEATURE_PLAGIARISM: 176 return true; 177 178 default: 179 return null; 180 } 181 } 182 183 /** 184 * Lists all gradable areas for the advanced grading methods gramework 185 * 186 * @return array('string'=>'string') An array with area names as keys and descriptions as values 187 */ 188 function assign_grading_areas_list() { 189 return array('submissions'=>get_string('submissions', 'assign')); 190 } 191 192 193 /** 194 * extend an assigment navigation settings 195 * 196 * @param settings_navigation $settings 197 * @param navigation_node $navref 198 * @return void 199 */ 200 function assign_extend_settings_navigation(settings_navigation $settings, navigation_node $navref) { 201 global $PAGE, $DB; 202 203 $cm = $PAGE->cm; 204 if (!$cm) { 205 return; 206 } 207 208 $context = $cm->context; 209 $course = $PAGE->course; 210 211 if (!$course) { 212 return; 213 } 214 215 // Link to gradebook. 216 if (has_capability('gradereport/grader:view', $cm->context) && 217 has_capability('moodle/grade:viewall', $cm->context)) { 218 $link = new moodle_url('/grade/report/grader/index.php', array('id' => $course->id)); 219 $linkname = get_string('viewgradebook', 'assign'); 220 $node = $navref->add($linkname, $link, navigation_node::TYPE_SETTING); 221 } 222 223 // Link to download all submissions. 224 if (has_any_capability(array('mod/assign:grade', 'mod/assign:viewgrades'), $context)) { 225 $link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id, 'action'=>'grading')); 226 $node = $navref->add(get_string('viewgrading', 'assign'), $link, navigation_node::TYPE_SETTING); 227 228 $link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id, 'action'=>'downloadall')); 229 $node = $navref->add(get_string('downloadall', 'assign'), $link, navigation_node::TYPE_SETTING); 230 } 231 232 if (has_capability('mod/assign:revealidentities', $context)) { 233 $dbparams = array('id'=>$cm->instance); 234 $assignment = $DB->get_record('assign', $dbparams, 'blindmarking, revealidentities'); 235 236 if ($assignment && $assignment->blindmarking && !$assignment->revealidentities) { 237 $urlparams = array('id' => $cm->id, 'action'=>'revealidentities'); 238 $url = new moodle_url('/mod/assign/view.php', $urlparams); 239 $linkname = get_string('revealidentities', 'assign'); 240 $node = $navref->add($linkname, $url, navigation_node::TYPE_SETTING); 241 } 242 } 243 } 244 245 /** 246 * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information 247 * for the course (see resource). 248 * 249 * Given a course_module object, this function returns any "extra" information that may be needed 250 * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. 251 * 252 * @param stdClass $coursemodule The coursemodule object (record). 253 * @return cached_cm_info An object on information that the courses 254 * will know about (most noticeably, an icon). 255 */ 256 function assign_get_coursemodule_info($coursemodule) { 257 global $CFG, $DB; 258 259 $dbparams = array('id'=>$coursemodule->instance); 260 $fields = 'id, name, alwaysshowdescription, allowsubmissionsfromdate, intro, introformat'; 261 if (! $assignment = $DB->get_record('assign', $dbparams, $fields)) { 262 return false; 263 } 264 265 $result = new cached_cm_info(); 266 $result->name = $assignment->name; 267 if ($coursemodule->showdescription) { 268 if ($assignment->alwaysshowdescription || time() > $assignment->allowsubmissionsfromdate) { 269 // Convert intro to html. Do not filter cached version, filters run at display time. 270 $result->content = format_module_intro('assign', $assignment, $coursemodule->id, false); 271 } 272 } 273 return $result; 274 } 275 276 /** 277 * Return a list of page types 278 * @param string $pagetype current page type 279 * @param stdClass $parentcontext Block's parent context 280 * @param stdClass $currentcontext Current context of block 281 */ 282 function assign_page_type_list($pagetype, $parentcontext, $currentcontext) { 283 $modulepagetype = array( 284 'mod-assign-*' => get_string('page-mod-assign-x', 'assign'), 285 'mod-assign-view' => get_string('page-mod-assign-view', 'assign'), 286 ); 287 return $modulepagetype; 288 } 289 290 /** 291 * Print an overview of all assignments 292 * for the courses. 293 * 294 * @param mixed $courses The list of courses to print the overview for 295 * @param array $htmlarray The array of html to return 296 */ 297 function assign_print_overview($courses, &$htmlarray) { 298 global $USER, $CFG, $DB; 299 300 if (empty($courses) || !is_array($courses) || count($courses) == 0) { 301 return array(); 302 } 303 304 if (!$assignments = get_all_instances_in_courses('assign', $courses)) { 305 return; 306 } 307 308 $assignmentids = array(); 309 310 // Do assignment_base::isopen() here without loading the whole thing for speed. 311 foreach ($assignments as $key => $assignment) { 312 $time = time(); 313 $isopen = false; 314 if ($assignment->duedate) { 315 $duedate = false; 316 if ($assignment->cutoffdate) { 317 $duedate = $assignment->cutoffdate; 318 } 319 if ($duedate) { 320 $isopen = ($assignment->allowsubmissionsfromdate <= $time && $time <= $duedate); 321 } else { 322 $isopen = ($assignment->allowsubmissionsfromdate <= $time); 323 } 324 } 325 if ($isopen) { 326 $assignmentids[] = $assignment->id; 327 } 328 } 329 330 if (empty($assignmentids)) { 331 // No assignments to look at - we're done. 332 return true; 333 } 334 335 // Definitely something to print, now include the constants we need. 336 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 337 338 $strduedate = get_string('duedate', 'assign'); 339 $strcutoffdate = get_string('nosubmissionsacceptedafter', 'assign'); 340 $strnolatesubmissions = get_string('nolatesubmissions', 'assign'); 341 $strduedateno = get_string('duedateno', 'assign'); 342 $strduedateno = get_string('duedateno', 'assign'); 343 $strgraded = get_string('graded', 'assign'); 344 $strnotgradedyet = get_string('notgradedyet', 'assign'); 345 $strnotsubmittedyet = get_string('notsubmittedyet', 'assign'); 346 $strsubmitted = get_string('submitted', 'assign'); 347 $strassignment = get_string('modulename', 'assign'); 348 $strreviewed = get_string('reviewed', 'assign'); 349 350 // We do all possible database work here *outside* of the loop to ensure this scales. 351 list($sqlassignmentids, $assignmentidparams) = $DB->get_in_or_equal($assignmentids); 352 353 $mysubmissions = null; 354 $unmarkedsubmissions = null; 355 356 foreach ($assignments as $assignment) { 357 // Do not show assignments that are not open. 358 if (!in_array($assignment->id, $assignmentids)) { 359 continue; 360 } 361 $dimmedclass = ''; 362 if (!$assignment->visible) { 363 $dimmedclass = ' class="dimmed"'; 364 } 365 $href = $CFG->wwwroot . '/mod/assign/view.php?id=' . $assignment->coursemodule; 366 $str = '<div class="assign overview">' . 367 '<div class="name">' . 368 $strassignment . ': '. 369 '<a ' . $dimmedclass . 370 'title="' . $strassignment . '" ' . 371 'href="' . $href . '">' . 372 format_string($assignment->name) . 373 '</a></div>'; 374 if ($assignment->duedate) { 375 $userdate = userdate($assignment->duedate); 376 $str .= '<div class="info">' . $strduedate . ': ' . $userdate . '</div>'; 377 } else { 378 $str .= '<div class="info">' . $strduedateno . '</div>'; 379 } 380 if ($assignment->cutoffdate) { 381 if ($assignment->cutoffdate == $assignment->duedate) { 382 $str .= '<div class="info">' . $strnolatesubmissions . '</div>'; 383 } else { 384 $userdate = userdate($assignment->cutoffdate); 385 $str .= '<div class="info">' . $strcutoffdate . ': ' . $userdate . '</div>'; 386 } 387 } 388 $context = context_module::instance($assignment->coursemodule); 389 if (has_capability('mod/assign:grade', $context)) { 390 if (!isset($unmarkedsubmissions)) { 391 // Build up and array of unmarked submissions indexed by assignment id/ userid 392 // for use where the user has grading rights on assignment. 393 $dbparams = array_merge(array(ASSIGN_SUBMISSION_STATUS_SUBMITTED), $assignmentidparams); 394 $rs = $DB->get_recordset_sql('SELECT 395 s.assignment as assignment, 396 s.userid as userid, 397 s.id as id, 398 s.status as status, 399 g.timemodified as timegraded 400 FROM {assign_submission} s 401 LEFT JOIN {assign_grades} g ON 402 s.userid = g.userid AND 403 s.assignment = g.assignment AND 404 g.attemptnumber = s.attemptnumber 405 WHERE 406 ( g.timemodified is NULL OR 407 s.timemodified > g.timemodified ) AND 408 s.timemodified IS NOT NULL AND 409 s.status = ? AND 410 s.latest = 1 AND 411 s.assignment ' . $sqlassignmentids, $dbparams); 412 413 $unmarkedsubmissions = array(); 414 foreach ($rs as $rd) { 415 $unmarkedsubmissions[$rd->assignment][$rd->userid] = $rd->id; 416 } 417 $rs->close(); 418 } 419 420 // Count how many people can submit. 421 $submissions = 0; 422 if ($students = get_enrolled_users($context, 'mod/assign:view', 0, 'u.id')) { 423 foreach ($students as $student) { 424 if (isset($unmarkedsubmissions[$assignment->id][$student->id])) { 425 $submissions++; 426 } 427 } 428 } 429 430 if ($submissions) { 431 $urlparams = array('id'=>$assignment->coursemodule, 'action'=>'grading'); 432 $url = new moodle_url('/mod/assign/view.php', $urlparams); 433 $str .= '<div class="details">' . 434 '<a href="' . $url . '">' . 435 get_string('submissionsnotgraded', 'assign', $submissions) . 436 '</a></div>'; 437 } 438 } 439 if (has_capability('mod/assign:submit', $context)) { 440 if (!isset($mysubmissions)) { 441 442 // Get all user submissions, indexed by assignment id. 443 $dbparams = array_merge(array($USER->id), $assignmentidparams, array($USER->id)); 444 $mysubmissions = $DB->get_records_sql('SELECT 445 a.id AS assignment, 446 a.nosubmissions AS nosubmissions, 447 g.timemodified AS timemarked, 448 g.grader AS grader, 449 g.grade AS grade, 450 s.status AS status 451 FROM {assign} a, {assign_submission} s 452 LEFT JOIN {assign_grades} g ON 453 g.assignment = s.assignment AND 454 g.userid = ? AND 455 g.attemptnumber = s.attemptnumber 456 WHERE a.id ' . $sqlassignmentids . ' AND 457 s.latest = 1 AND 458 s.assignment = a.id AND 459 s.userid = ?', $dbparams); 460 } 461 462 $str .= '<div class="details">'; 463 $str .= get_string('mysubmission', 'assign'); 464 $submission = false; 465 if (isset($mysubmissions[$assignment->id])) { 466 $submission = $mysubmissions[$assignment->id]; 467 } 468 if ($submission && $submission->nosubmissions) { 469 $str .= get_string('offline', 'assign'); 470 } else if (!$submission || 471 !$submission->status || 472 $submission->status == 'draft' || 473 $submission->status == 'new') { 474 $str .= $strnotsubmittedyet; 475 } else { 476 $str .= get_string('submissionstatus_' . $submission->status, 'assign'); 477 } 478 if (!$submission || !$submission->grade || $submission->grade < 0) { 479 $str .= ', ' . get_string('notgraded', 'assign'); 480 } else { 481 $str .= ', ' . get_string('graded', 'assign'); 482 } 483 $str .= '</div>'; 484 } 485 $str .= '</div>'; 486 if (empty($htmlarray[$assignment->course]['assign'])) { 487 $htmlarray[$assignment->course]['assign'] = $str; 488 } else { 489 $htmlarray[$assignment->course]['assign'] .= $str; 490 } 491 } 492 } 493 494 /** 495 * Print recent activity from all assignments in a given course 496 * 497 * This is used by the recent activity block 498 * @param mixed $course the course to print activity for 499 * @param bool $viewfullnames boolean to determine whether to show full names or not 500 * @param int $timestart the time the rendering started 501 * @return bool true if activity was printed, false otherwise. 502 */ 503 function assign_print_recent_activity($course, $viewfullnames, $timestart) { 504 global $CFG, $USER, $DB, $OUTPUT; 505 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 506 507 // Do not use log table if possible, it may be huge. 508 509 $dbparams = array($timestart, $course->id, 'assign', ASSIGN_SUBMISSION_STATUS_SUBMITTED); 510 $namefields = user_picture::fields('u', null, 'userid'); 511 if (!$submissions = $DB->get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, 512 $namefields 513 FROM {assign_submission} asb 514 JOIN {assign} a ON a.id = asb.assignment 515 JOIN {course_modules} cm ON cm.instance = a.id 516 JOIN {modules} md ON md.id = cm.module 517 JOIN {user} u ON u.id = asb.userid 518 WHERE asb.timemodified > ? AND 519 asb.latest = 1 AND 520 a.course = ? AND 521 md.name = ? AND 522 asb.status = ? 523 ORDER BY asb.timemodified ASC", $dbparams)) { 524 return false; 525 } 526 527 $modinfo = get_fast_modinfo($course); 528 $show = array(); 529 $grader = array(); 530 531 $showrecentsubmissions = get_config('assign', 'showrecentsubmissions'); 532 533 foreach ($submissions as $submission) { 534 if (!array_key_exists($submission->cmid, $modinfo->get_cms())) { 535 continue; 536 } 537 $cm = $modinfo->get_cm($submission->cmid); 538 if (!$cm->uservisible) { 539 continue; 540 } 541 if ($submission->userid == $USER->id) { 542 $show[] = $submission; 543 continue; 544 } 545 546 $context = context_module::instance($submission->cmid); 547 // The act of submitting of assignment may be considered private - 548 // only graders will see it if specified. 549 if (empty($showrecentsubmissions)) { 550 if (!array_key_exists($cm->id, $grader)) { 551 $grader[$cm->id] = has_capability('moodle/grade:viewall', $context); 552 } 553 if (!$grader[$cm->id]) { 554 continue; 555 } 556 } 557 558 $groupmode = groups_get_activity_groupmode($cm, $course); 559 560 if ($groupmode == SEPARATEGROUPS && 561 !has_capability('moodle/site:accessallgroups', $context)) { 562 if (isguestuser()) { 563 // Shortcut - guest user does not belong into any group. 564 continue; 565 } 566 567 // This will be slow - show only users that share group with me in this cm. 568 if (!$modinfo->get_groups($cm->groupingid)) { 569 continue; 570 } 571 $usersgroups = groups_get_all_groups($course->id, $submission->userid, $cm->groupingid); 572 if (is_array($usersgroups)) { 573 $usersgroups = array_keys($usersgroups); 574 $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid)); 575 if (empty($intersect)) { 576 continue; 577 } 578 } 579 } 580 $show[] = $submission; 581 } 582 583 if (empty($show)) { 584 return false; 585 } 586 587 echo $OUTPUT->heading(get_string('newsubmissions', 'assign').':', 3); 588 589 foreach ($show as $submission) { 590 $cm = $modinfo->get_cm($submission->cmid); 591 $link = $CFG->wwwroot.'/mod/assign/view.php?id='.$cm->id; 592 print_recent_activity_note($submission->timemodified, 593 $submission, 594 $cm->name, 595 $link, 596 false, 597 $viewfullnames); 598 } 599 600 return true; 601 } 602 603 /** 604 * Returns all assignments since a given time. 605 * 606 * @param array $activities The activity information is returned in this array 607 * @param int $index The current index in the activities array 608 * @param int $timestart The earliest activity to show 609 * @param int $courseid Limit the search to this course 610 * @param int $cmid The course module id 611 * @param int $userid Optional user id 612 * @param int $groupid Optional group id 613 * @return void 614 */ 615 function assign_get_recent_mod_activity(&$activities, 616 &$index, 617 $timestart, 618 $courseid, 619 $cmid, 620 $userid=0, 621 $groupid=0) { 622 global $CFG, $COURSE, $USER, $DB; 623 624 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 625 626 if ($COURSE->id == $courseid) { 627 $course = $COURSE; 628 } else { 629 $course = $DB->get_record('course', array('id'=>$courseid)); 630 } 631 632 $modinfo = get_fast_modinfo($course); 633 634 $cm = $modinfo->get_cm($cmid); 635 $params = array(); 636 if ($userid) { 637 $userselect = 'AND u.id = :userid'; 638 $params['userid'] = $userid; 639 } else { 640 $userselect = ''; 641 } 642 643 if ($groupid) { 644 $groupselect = 'AND gm.groupid = :groupid'; 645 $groupjoin = 'JOIN {groups_members} gm ON gm.userid=u.id'; 646 $params['groupid'] = $groupid; 647 } else { 648 $groupselect = ''; 649 $groupjoin = ''; 650 } 651 652 $params['cminstance'] = $cm->instance; 653 $params['timestart'] = $timestart; 654 $params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED; 655 656 $userfields = user_picture::fields('u', null, 'userid'); 657 658 if (!$submissions = $DB->get_records_sql('SELECT asb.id, asb.timemodified, ' . 659 $userfields . 660 ' FROM {assign_submission} asb 661 JOIN {assign} a ON a.id = asb.assignment 662 JOIN {user} u ON u.id = asb.userid ' . 663 $groupjoin . 664 ' WHERE asb.timemodified > :timestart AND 665 asb.status = :submitted AND 666 a.id = :cminstance 667 ' . $userselect . ' ' . $groupselect . 668 ' ORDER BY asb.timemodified ASC', $params)) { 669 return; 670 } 671 672 $groupmode = groups_get_activity_groupmode($cm, $course); 673 $cmcontext = context_module::instance($cm->id); 674 $grader = has_capability('moodle/grade:viewall', $cmcontext); 675 $accessallgroups = has_capability('moodle/site:accessallgroups', $cmcontext); 676 $viewfullnames = has_capability('moodle/site:viewfullnames', $cmcontext); 677 678 679 $showrecentsubmissions = get_config('assign', 'showrecentsubmissions'); 680 $show = array(); 681 foreach ($submissions as $submission) { 682 if ($submission->userid == $USER->id) { 683 $show[] = $submission; 684 continue; 685 } 686 // The act of submitting of assignment may be considered private - 687 // only graders will see it if specified. 688 if (empty($showrecentsubmissions)) { 689 if (!$grader) { 690 continue; 691 } 692 } 693 694 if ($groupmode == SEPARATEGROUPS and !$accessallgroups) { 695 if (isguestuser()) { 696 // Shortcut - guest user does not belong into any group. 697 continue; 698 } 699 700 // This will be slow - show only users that share group with me in this cm. 701 if (!$modinfo->get_groups($cm->groupingid)) { 702 continue; 703 } 704 $usersgroups = groups_get_all_groups($course->id, $submission->userid, $cm->groupingid); 705 if (is_array($usersgroups)) { 706 $usersgroups = array_keys($usersgroups); 707 $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid)); 708 if (empty($intersect)) { 709 continue; 710 } 711 } 712 } 713 $show[] = $submission; 714 } 715 716 if (empty($show)) { 717 return; 718 } 719 720 if ($grader) { 721 require_once($CFG->libdir.'/gradelib.php'); 722 $userids = array(); 723 foreach ($show as $id => $submission) { 724 $userids[] = $submission->userid; 725 } 726 $grades = grade_get_grades($courseid, 'mod', 'assign', $cm->instance, $userids); 727 } 728 729 $aname = format_string($cm->name, true); 730 foreach ($show as $submission) { 731 $activity = new stdClass(); 732 733 $activity->type = 'assign'; 734 $activity->cmid = $cm->id; 735 $activity->name = $aname; 736 $activity->sectionnum = $cm->sectionnum; 737 $activity->timestamp = $submission->timemodified; 738 $activity->user = new stdClass(); 739 if ($grader) { 740 $activity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade; 741 } 742 743 $userfields = explode(',', user_picture::fields()); 744 foreach ($userfields as $userfield) { 745 if ($userfield == 'id') { 746 // Aliased in SQL above. 747 $activity->user->{$userfield} = $submission->userid; 748 } else { 749 $activity->user->{$userfield} = $submission->{$userfield}; 750 } 751 } 752 $activity->user->fullname = fullname($submission, $viewfullnames); 753 754 $activities[$index++] = $activity; 755 } 756 757 return; 758 } 759 760 /** 761 * Print recent activity from all assignments in a given course 762 * 763 * This is used by course/recent.php 764 * @param stdClass $activity 765 * @param int $courseid 766 * @param bool $detail 767 * @param array $modnames 768 */ 769 function assign_print_recent_mod_activity($activity, $courseid, $detail, $modnames) { 770 global $CFG, $OUTPUT; 771 772 echo '<table border="0" cellpadding="3" cellspacing="0" class="assignment-recent">'; 773 774 echo '<tr><td class="userpicture" valign="top">'; 775 echo $OUTPUT->user_picture($activity->user); 776 echo '</td><td>'; 777 778 if ($detail) { 779 $modname = $modnames[$activity->type]; 780 echo '<div class="title">'; 781 echo '<img src="' . $OUTPUT->pix_url('icon', 'assign') . '" '. 782 'class="icon" alt="' . $modname . '">'; 783 echo '<a href="' . $CFG->wwwroot . '/mod/assign/view.php?id=' . $activity->cmid . '">'; 784 echo $activity->name; 785 echo '</a>'; 786 echo '</div>'; 787 } 788 789 if (isset($activity->grade)) { 790 echo '<div class="grade">'; 791 echo get_string('grade').': '; 792 echo $activity->grade; 793 echo '</div>'; 794 } 795 796 echo '<div class="user">'; 797 echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->id}&course=$courseid\">"; 798 echo "{$activity->user->fullname}</a> - " . userdate($activity->timestamp); 799 echo '</div>'; 800 801 echo '</td></tr></table>'; 802 } 803 804 /** 805 * Checks if a scale is being used by an assignment. 806 * 807 * This is used by the backup code to decide whether to back up a scale 808 * @param int $assignmentid 809 * @param int $scaleid 810 * @return boolean True if the scale is used by the assignment 811 */ 812 function assign_scale_used($assignmentid, $scaleid) { 813 global $DB; 814 815 $return = false; 816 $rec = $DB->get_record('assign', array('id'=>$assignmentid, 'grade'=>-$scaleid)); 817 818 if (!empty($rec) && !empty($scaleid)) { 819 $return = true; 820 } 821 822 return $return; 823 } 824 825 /** 826 * Checks if scale is being used by any instance of assignment 827 * 828 * This is used to find out if scale used anywhere 829 * @param int $scaleid 830 * @return boolean True if the scale is used by any assignment 831 */ 832 function assign_scale_used_anywhere($scaleid) { 833 global $DB; 834 835 if ($scaleid and $DB->record_exists('assign', array('grade'=>-$scaleid))) { 836 return true; 837 } else { 838 return false; 839 } 840 } 841 842 /** 843 * List the actions that correspond to a view of this module. 844 * This is used by the participation report. 845 * 846 * Note: This is not used by new logging system. Event with 847 * crud = 'r' and edulevel = LEVEL_PARTICIPATING will 848 * be considered as view action. 849 * 850 * @return array 851 */ 852 function assign_get_view_actions() { 853 return array('view submission', 'view feedback'); 854 } 855 856 /** 857 * List the actions that correspond to a post of this module. 858 * This is used by the participation report. 859 * 860 * Note: This is not used by new logging system. Event with 861 * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING 862 * will be considered as post action. 863 * 864 * @return array 865 */ 866 function assign_get_post_actions() { 867 return array('upload', 'submit', 'submit for grading'); 868 } 869 870 /** 871 * Call cron on the assign module. 872 */ 873 function assign_cron() { 874 global $CFG; 875 876 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 877 assign::cron(); 878 879 $plugins = core_component::get_plugin_list('assignsubmission'); 880 881 foreach ($plugins as $name => $plugin) { 882 $disabled = get_config('assignsubmission_' . $name, 'disabled'); 883 if (!$disabled) { 884 $class = 'assign_submission_' . $name; 885 require_once($CFG->dirroot . '/mod/assign/submission/' . $name . '/locallib.php'); 886 $class::cron(); 887 } 888 } 889 $plugins = core_component::get_plugin_list('assignfeedback'); 890 891 foreach ($plugins as $name => $plugin) { 892 $disabled = get_config('assignfeedback_' . $name, 'disabled'); 893 if (!$disabled) { 894 $class = 'assign_feedback_' . $name; 895 require_once($CFG->dirroot . '/mod/assign/feedback/' . $name . '/locallib.php'); 896 $class::cron(); 897 } 898 } 899 900 return true; 901 } 902 903 /** 904 * Returns all other capabilities used by this module. 905 * @return array Array of capability strings 906 */ 907 function assign_get_extra_capabilities() { 908 return array('gradereport/grader:view', 909 'moodle/grade:viewall', 910 'moodle/site:viewfullnames', 911 'moodle/site:config'); 912 } 913 914 /** 915 * Create grade item for given assignment. 916 * 917 * @param stdClass $assign record with extra cmidnumber 918 * @param array $grades optional array/object of grade(s); 'reset' means reset grades in gradebook 919 * @return int 0 if ok, error code otherwise 920 */ 921 function assign_grade_item_update($assign, $grades=null) { 922 global $CFG; 923 require_once($CFG->libdir.'/gradelib.php'); 924 925 if (!isset($assign->courseid)) { 926 $assign->courseid = $assign->course; 927 } 928 929 $params = array('itemname'=>$assign->name, 'idnumber'=>$assign->cmidnumber); 930 931 // Check if feedback plugin for gradebook is enabled, if yes then 932 // gradetype = GRADE_TYPE_TEXT else GRADE_TYPE_NONE. 933 $gradefeedbackenabled = false; 934 935 if (isset($assign->gradefeedbackenabled)) { 936 $gradefeedbackenabled = $assign->gradefeedbackenabled; 937 } else if ($assign->grade == 0) { // Grade feedback is needed only when grade == 0. 938 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 939 $mod = get_coursemodule_from_instance('assign', $assign->id, $assign->courseid); 940 $cm = context_module::instance($mod->id); 941 $assignment = new assign($cm, null, null); 942 $gradefeedbackenabled = $assignment->is_gradebook_feedback_enabled(); 943 } 944 945 if ($assign->grade > 0) { 946 $params['gradetype'] = GRADE_TYPE_VALUE; 947 $params['grademax'] = $assign->grade; 948 $params['grademin'] = 0; 949 950 } else if ($assign->grade < 0) { 951 $params['gradetype'] = GRADE_TYPE_SCALE; 952 $params['scaleid'] = -$assign->grade; 953 954 } else if ($gradefeedbackenabled) { 955 // $assign->grade == 0 and feedback enabled. 956 $params['gradetype'] = GRADE_TYPE_TEXT; 957 } else { 958 // $assign->grade == 0 and no feedback enabled. 959 $params['gradetype'] = GRADE_TYPE_NONE; 960 } 961 962 if ($grades === 'reset') { 963 $params['reset'] = true; 964 $grades = null; 965 } 966 967 return grade_update('mod/assign', 968 $assign->courseid, 969 'mod', 970 'assign', 971 $assign->id, 972 0, 973 $grades, 974 $params); 975 } 976 977 /** 978 * Return grade for given user or all users. 979 * 980 * @param stdClass $assign record of assign with an additional cmidnumber 981 * @param int $userid optional user id, 0 means all users 982 * @return array array of grades, false if none 983 */ 984 function assign_get_user_grades($assign, $userid=0) { 985 global $CFG; 986 987 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 988 989 $cm = get_coursemodule_from_instance('assign', $assign->id, 0, false, MUST_EXIST); 990 $context = context_module::instance($cm->id); 991 $assignment = new assign($context, null, null); 992 $assignment->set_instance($assign); 993 return $assignment->get_user_grades_for_gradebook($userid); 994 } 995 996 /** 997 * Update activity grades. 998 * 999 * @param stdClass $assign database record 1000 * @param int $userid specific user only, 0 means all 1001 * @param bool $nullifnone - not used 1002 */ 1003 function assign_update_grades($assign, $userid=0, $nullifnone=true) { 1004 global $CFG; 1005 require_once($CFG->libdir.'/gradelib.php'); 1006 1007 if ($assign->grade == 0) { 1008 assign_grade_item_update($assign); 1009 1010 } else if ($grades = assign_get_user_grades($assign, $userid)) { 1011 foreach ($grades as $k => $v) { 1012 if ($v->rawgrade == -1) { 1013 $grades[$k]->rawgrade = null; 1014 } 1015 } 1016 assign_grade_item_update($assign, $grades); 1017 1018 } else { 1019 assign_grade_item_update($assign); 1020 } 1021 } 1022 1023 /** 1024 * List the file areas that can be browsed. 1025 * 1026 * @param stdClass $course 1027 * @param stdClass $cm 1028 * @param stdClass $context 1029 * @return array 1030 */ 1031 function assign_get_file_areas($course, $cm, $context) { 1032 global $CFG; 1033 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 1034 1035 $areas = array(ASSIGN_INTROATTACHMENT_FILEAREA => get_string('introattachments', 'mod_assign')); 1036 1037 $assignment = new assign($context, $cm, $course); 1038 foreach ($assignment->get_submission_plugins() as $plugin) { 1039 if ($plugin->is_visible()) { 1040 $pluginareas = $plugin->get_file_areas(); 1041 1042 if ($pluginareas) { 1043 $areas = array_merge($areas, $pluginareas); 1044 } 1045 } 1046 } 1047 foreach ($assignment->get_feedback_plugins() as $plugin) { 1048 if ($plugin->is_visible()) { 1049 $pluginareas = $plugin->get_file_areas(); 1050 1051 if ($pluginareas) { 1052 $areas = array_merge($areas, $pluginareas); 1053 } 1054 } 1055 } 1056 1057 return $areas; 1058 } 1059 1060 /** 1061 * File browsing support for assign module. 1062 * 1063 * @param file_browser $browser 1064 * @param object $areas 1065 * @param object $course 1066 * @param object $cm 1067 * @param object $context 1068 * @param string $filearea 1069 * @param int $itemid 1070 * @param string $filepath 1071 * @param string $filename 1072 * @return object file_info instance or null if not found 1073 */ 1074 function assign_get_file_info($browser, 1075 $areas, 1076 $course, 1077 $cm, 1078 $context, 1079 $filearea, 1080 $itemid, 1081 $filepath, 1082 $filename) { 1083 global $CFG; 1084 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 1085 1086 if ($context->contextlevel != CONTEXT_MODULE) { 1087 return null; 1088 } 1089 1090 $urlbase = $CFG->wwwroot.'/pluginfile.php'; 1091 $fs = get_file_storage(); 1092 $filepath = is_null($filepath) ? '/' : $filepath; 1093 $filename = is_null($filename) ? '.' : $filename; 1094 1095 // Need to find where this belongs to. 1096 $assignment = new assign($context, $cm, $course); 1097 if ($filearea === ASSIGN_INTROATTACHMENT_FILEAREA) { 1098 if (!has_capability('moodle/course:managefiles', $context)) { 1099 // Students can not peak here! 1100 return null; 1101 } 1102 if (!($storedfile = $fs->get_file($assignment->get_context()->id, 1103 'mod_assign', $filearea, 0, $filepath, $filename))) { 1104 return null; 1105 } 1106 return new file_info_stored($browser, 1107 $assignment->get_context(), 1108 $storedfile, 1109 $urlbase, 1110 $filearea, 1111 $itemid, 1112 true, 1113 true, 1114 false); 1115 } 1116 1117 $pluginowner = null; 1118 foreach ($assignment->get_submission_plugins() as $plugin) { 1119 if ($plugin->is_visible()) { 1120 $pluginareas = $plugin->get_file_areas(); 1121 1122 if (array_key_exists($filearea, $pluginareas)) { 1123 $pluginowner = $plugin; 1124 break; 1125 } 1126 } 1127 } 1128 if (!$pluginowner) { 1129 foreach ($assignment->get_feedback_plugins() as $plugin) { 1130 if ($plugin->is_visible()) { 1131 $pluginareas = $plugin->get_file_areas(); 1132 1133 if (array_key_exists($filearea, $pluginareas)) { 1134 $pluginowner = $plugin; 1135 break; 1136 } 1137 } 1138 } 1139 } 1140 1141 if (!$pluginowner) { 1142 return null; 1143 } 1144 1145 $result = $pluginowner->get_file_info($browser, $filearea, $itemid, $filepath, $filename); 1146 return $result; 1147 } 1148 1149 /** 1150 * Prints the complete info about a user's interaction with an assignment. 1151 * 1152 * @param stdClass $course 1153 * @param stdClass $user 1154 * @param stdClass $coursemodule 1155 * @param stdClass $assign the database assign record 1156 * 1157 * This prints the submission summary and feedback summary for this student. 1158 */ 1159 function assign_user_complete($course, $user, $coursemodule, $assign) { 1160 global $CFG; 1161 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 1162 1163 $context = context_module::instance($coursemodule->id); 1164 1165 $assignment = new assign($context, $coursemodule, $course); 1166 1167 echo $assignment->view_student_summary($user, false); 1168 } 1169 1170 /** 1171 * Print the grade information for the assignment for this user. 1172 * 1173 * @param stdClass $course 1174 * @param stdClass $user 1175 * @param stdClass $coursemodule 1176 * @param stdClass $assignment 1177 */ 1178 function assign_user_outline($course, $user, $coursemodule, $assignment) { 1179 global $CFG; 1180 require_once($CFG->libdir.'/gradelib.php'); 1181 require_once($CFG->dirroot.'/grade/grading/lib.php'); 1182 1183 $gradinginfo = grade_get_grades($course->id, 1184 'mod', 1185 'assign', 1186 $assignment->id, 1187 $user->id); 1188 1189 $gradingitem = $gradinginfo->items[0]; 1190 $gradebookgrade = $gradingitem->grades[$user->id]; 1191 1192 if (empty($gradebookgrade->str_long_grade)) { 1193 return null; 1194 } 1195 $result = new stdClass(); 1196 $result->info = get_string('outlinegrade', 'assign', $gradebookgrade->str_long_grade); 1197 $result->time = $gradebookgrade->dategraded; 1198 1199 return $result; 1200 } 1201 1202 /** 1203 * Obtains the automatic completion state for this module based on any conditions 1204 * in assign settings. 1205 * 1206 * @param object $course Course 1207 * @param object $cm Course-module 1208 * @param int $userid User ID 1209 * @param bool $type Type of comparison (or/and; can be used as return value if no conditions) 1210 * @return bool True if completed, false if not, $type if conditions not set. 1211 */ 1212 function assign_get_completion_state($course, $cm, $userid, $type) { 1213 global $CFG, $DB; 1214 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 1215 1216 $assign = new assign(null, $cm, $course); 1217 1218 // If completion option is enabled, evaluate it and return true/false. 1219 if ($assign->get_instance()->completionsubmit) { 1220 $dbparams = array('assignment'=>$assign->get_instance()->id, 'userid'=>$userid); 1221 $submission = $DB->get_record('assign_submission', $dbparams, '*', IGNORE_MISSING); 1222 return $submission && $submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED; 1223 } else { 1224 // Completion option is not enabled so just return $type. 1225 return $type; 1226 } 1227 } 1228 1229 /** 1230 * Serves intro attachment files. 1231 * 1232 * @param mixed $course course or id of the course 1233 * @param mixed $cm course module or id of the course module 1234 * @param context $context 1235 * @param string $filearea 1236 * @param array $args 1237 * @param bool $forcedownload 1238 * @param array $options additional options affecting the file serving 1239 * @return bool false if file not found, does not return if found - just send the file 1240 */ 1241 function assign_pluginfile($course, 1242 $cm, 1243 context $context, 1244 $filearea, 1245 $args, 1246 $forcedownload, 1247 array $options=array()) { 1248 global $CFG; 1249 1250 if ($context->contextlevel != CONTEXT_MODULE) { 1251 return false; 1252 } 1253 1254 require_login($course, false, $cm); 1255 if (!has_capability('mod/assign:view', $context)) { 1256 return false; 1257 } 1258 1259 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 1260 $assign = new assign($context, $cm, $course); 1261 1262 if ($filearea !== ASSIGN_INTROATTACHMENT_FILEAREA) { 1263 return false; 1264 } 1265 if (!$assign->show_intro()) { 1266 return false; 1267 } 1268 1269 $itemid = (int)array_shift($args); 1270 if ($itemid != 0) { 1271 return false; 1272 } 1273 1274 $relativepath = implode('/', $args); 1275 1276 $fullpath = "/{$context->id}/mod_assign/$filearea/$itemid/$relativepath"; 1277 1278 $fs = get_file_storage(); 1279 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { 1280 return false; 1281 } 1282 send_stored_file($file, 0, 0, $forcedownload, $options); 1283 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |