/** * Format a column of data for display. * * @param stdClass $row * @return string */ public function col_grade(stdClass $row) { $o = ''; $link = ''; $separator = $this->output->spacer(array(), true); $grade = ''; $gradingdisabled = $this->assignment->grading_disabled($row->id); if (!$this->is_downloading() && $this->hasgrade) { $name = fullname($row); if ($this->assignment->is_blind_marking()) { $name = get_string('hiddenuser', 'assign') . $this->assignment->get_uniqueid_for_user($row->userid); } $icon = $this->output->pix_icon('gradefeedback', get_string('gradeuser', 'assign', $name), 'mod_assign'); $urlparams = array('id' => $this->assignment->get_course_module()->id, 'rownum'=>$this->rownum, 'action'=>'grade'); $url = new moodle_url('/mod/assign/view.php', $urlparams); $link = $this->output->action_link($url, $icon); $grade .= $link . $separator; } $grade .= $this->display_grade($row->grade, $this->quickgrading && !$gradingdisabled, $row->userid, $row->timemarked); return $grade; }
/** * Format a column of data for display. * * @param stdClass $row * @return string */ public function col_grade(stdClass $row) { $o = ''; $link = ''; $separator = $this->output->spacer(array(), true); $grade = ''; $gradingdisabled = $this->assignment->grading_disabled($row->id); if (!$this->is_downloading() && $this->hasgrade) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'rownum' => 0, 'action' => 'grader'); if ($this->assignment->is_blind_marking()) { $urlparams['blindid'] = $this->assignment->get_uniqueid_for_user($row->userid); } else { $urlparams['userid'] = $row->userid; } $url = new moodle_url('/mod/assign/view.php', $urlparams); $link = '<a href="' . $url . '" class="btn btn-primary">' . get_string('grade') . '</a>'; $grade .= $link . $separator; } $grade .= $this->display_grade($row->grade, $this->quickgrading && !$gradingdisabled, $row->userid, $row->timemarked); return $grade; }
/** * overridden constructor keeps a reference to the assignment class that is displaying this table * * @param assign $assignment The assignment class * @param int $perpage how many per page * @param string $filter The current filter * @param int $rowoffset For showing a subsequent page of results * @param bool $quickgrading Is this table wrapped in a quickgrading form? * @param string $downloadfilename */ public function __construct(assign $assignment, $perpage, $filter, $rowoffset, $quickgrading, $downloadfilename = null) { global $CFG, $PAGE, $DB, $USER; parent::__construct('mod_assign_grading'); $this->is_persistent(true); $this->assignment = $assignment; // Check permissions up front. $this->hasgrantextension = has_capability('mod/assign:grantextension', $this->assignment->get_context()); $this->hasgrade = $this->assignment->can_grade(); // Check if we have the elevated view capablities to see the blind details. $this->hasviewblind = has_capability('mod/assign:viewblinddetails', $this->assignment->get_context()); foreach ($assignment->get_feedback_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled()) { foreach ($plugin->get_grading_batch_operations() as $action => $description) { if (empty($this->plugingradingbatchoperations)) { $this->plugingradingbatchoperations[$plugin->get_type()] = array(); } $this->plugingradingbatchoperations[$plugin->get_type()][$action] = $description; } } } $this->perpage = $perpage; $this->quickgrading = $quickgrading && $this->hasgrade; $this->output = $PAGE->get_renderer('mod_assign'); $urlparams = array('action' => 'grading', 'id' => $assignment->get_course_module()->id); $url = new moodle_url($CFG->wwwroot . '/mod/assign/view.php', $urlparams); $this->define_baseurl($url); // Do some business - then set the sql. $currentgroup = groups_get_activity_group($assignment->get_course_module(), true); if ($rowoffset) { $this->rownum = $rowoffset - 1; } $users = array_keys($assignment->list_participants($currentgroup, true)); if (count($users) == 0) { // Insert a record that will never match to the sql is still valid. $users[] = -1; } $params = array(); $params['assignmentid1'] = (int) $this->assignment->get_instance()->id; $params['assignmentid2'] = (int) $this->assignment->get_instance()->id; $params['assignmentid3'] = (int) $this->assignment->get_instance()->id; $extrauserfields = get_extra_user_fields($this->assignment->get_context()); $fields = user_picture::fields('u', $extrauserfields) . ', '; $fields .= 'u.id as userid, '; $fields .= 's.status as status, '; $fields .= 's.id as submissionid, '; $fields .= 's.timecreated as firstsubmission, '; $fields .= 's.timemodified as timesubmitted, '; $fields .= 's.attemptnumber as attemptnumber, '; $fields .= 'g.id as gradeid, '; $fields .= 'g.grade as grade, '; $fields .= 'g.timemodified as timemarked, '; $fields .= 'g.timecreated as firstmarked, '; $fields .= 'uf.mailed as mailed, '; $fields .= 'uf.locked as locked, '; $fields .= 'uf.extensionduedate as extensionduedate, '; $fields .= 'uf.workflowstate as workflowstate, '; $fields .= 'uf.allocatedmarker as allocatedmarker '; $from = '{user} u LEFT JOIN {assign_submission} s ON u.id = s.userid AND s.assignment = :assignmentid1 AND s.latest = 1 LEFT JOIN {assign_grades} g ON u.id = g.userid AND g.assignment = :assignmentid2 '; // For group submissions we don't immediately create an entry in the assign_submission table for each user, // instead the userid is set to 0. In this case we use a different query to retrieve the grade for the user. if ($this->assignment->get_instance()->teamsubmission) { $params['assignmentid4'] = (int) $this->assignment->get_instance()->id; $grademaxattempt = 'SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt FROM {assign_grades} mxg WHERE mxg.assignment = :assignmentid4 GROUP BY mxg.userid'; $from .= 'LEFT JOIN (' . $grademaxattempt . ') gmx ON u.id = gmx.userid AND g.attemptnumber = gmx.maxattempt '; } else { $from .= 'AND g.attemptnumber = s.attemptnumber '; } $from .= 'LEFT JOIN {assign_user_flags} uf ON u.id = uf.userid AND uf.assignment = :assignmentid3'; $userparams = array(); $userindex = 0; list($userwhere, $userparams) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED, 'user'); $where = 'u.id ' . $userwhere; $params = array_merge($params, $userparams); // The filters do not make sense when there are no submissions, so do not apply them. if ($this->assignment->is_any_submission_plugin_enabled()) { if ($filter == ASSIGN_FILTER_SUBMITTED) { $where .= ' AND (s.timemodified IS NOT NULL AND s.status = :submitted) '; $params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED; } else { if ($filter == ASSIGN_FILTER_NOT_SUBMITTED) { $where .= ' AND (s.timemodified IS NULL OR s.status != :submitted) '; $params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED; } else { if ($filter == ASSIGN_FILTER_REQUIRE_GRADING) { $where .= ' AND (s.timemodified IS NOT NULL AND s.status = :submitted AND (s.timemodified >= g.timemodified OR g.timemodified IS NULL OR g.grade IS NULL))'; $params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED; } else { if (strpos($filter, ASSIGN_FILTER_SINGLE_USER) === 0) { $userfilter = (int) array_pop(explode('=', $filter)); $where .= ' AND (u.id = :userid)'; $params['userid'] = $userfilter; } } } } } if ($this->assignment->get_instance()->markingworkflow && $this->assignment->get_instance()->markingallocation) { if (has_capability('mod/assign:manageallocations', $this->assignment->get_context())) { // Check to see if marker filter is set. $markerfilter = (int) get_user_preferences('assign_markerfilter', ''); if (!empty($markerfilter)) { if ($markerfilter == ASSIGN_MARKER_FILTER_NO_MARKER) { $where .= ' AND (uf.allocatedmarker IS NULL OR uf.allocatedmarker = 0)'; } else { $where .= ' AND uf.allocatedmarker = :markerid'; $params['markerid'] = $markerfilter; } } } else { // Only show users allocated to this marker. $where .= ' AND uf.allocatedmarker = :markerid'; $params['markerid'] = $USER->id; } } if ($this->assignment->get_instance()->markingworkflow) { $workflowstates = $this->assignment->get_marking_workflow_states_for_current_user(); if (!empty($workflowstates)) { $workflowfilter = get_user_preferences('assign_workflowfilter', ''); if ($workflowfilter == ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED) { $where .= ' AND (uf.workflowstate = :workflowstate OR uf.workflowstate IS NULL OR ' . $DB->sql_isempty('assign_user_flags', 'workflowstate', true, true) . ')'; $params['workflowstate'] = $workflowfilter; } else { if (array_key_exists($workflowfilter, $workflowstates)) { $where .= ' AND uf.workflowstate = :workflowstate'; $params['workflowstate'] = $workflowfilter; } } } } $this->set_sql($fields, $from, $where, $params); if ($downloadfilename) { $this->is_downloading('csv', $downloadfilename); } $columns = array(); $headers = array(); // Select. if (!$this->is_downloading() && $this->hasgrade) { $columns[] = 'select'; $headers[] = get_string('select') . '<div class="selectall"><label class="accesshide" for="selectall">' . get_string('selectall') . '</label> <input type="checkbox" id="selectall" name="selectall" title="' . get_string('selectall') . '"/></div>'; } // User picture. if ($this->hasviewblind || !$this->assignment->is_blind_marking()) { if (!$this->is_downloading()) { $columns[] = 'picture'; $headers[] = get_string('pictureofuser'); } else { $columns[] = 'recordid'; $headers[] = get_string('recordid', 'assign'); } // Fullname. $columns[] = 'fullname'; $headers[] = get_string('fullname'); foreach ($extrauserfields as $extrafield) { $columns[] = $extrafield; $headers[] = get_user_field_name($extrafield); } } else { // Record ID. $columns[] = 'recordid'; $headers[] = get_string('recordid', 'assign'); } // Submission status. $columns[] = 'status'; $headers[] = get_string('status', 'assign'); // Team submission columns. if ($assignment->get_instance()->teamsubmission) { $columns[] = 'team'; $headers[] = get_string('submissionteam', 'assign'); } // Allocated marker. if ($this->assignment->get_instance()->markingworkflow && $this->assignment->get_instance()->markingallocation && has_capability('mod/assign:manageallocations', $this->assignment->get_context())) { // Add a column for the allocated marker. $columns[] = 'allocatedmarker'; $headers[] = get_string('marker', 'assign'); } // Grade. $columns[] = 'grade'; $headers[] = get_string('grade'); if ($this->is_downloading()) { if ($this->assignment->get_instance()->grade >= 0) { $columns[] = 'grademax'; $headers[] = get_string('maxgrade', 'assign'); } else { // This is a custom scale. $columns[] = 'scale'; $headers[] = get_string('scale', 'assign'); } if ($this->assignment->get_instance()->markingworkflow) { // Add a column for the marking workflow state. $columns[] = 'workflowstate'; $headers[] = get_string('markingworkflowstate', 'assign'); } // Add a column for the list of valid marking workflow states. $columns[] = 'gradecanbechanged'; $headers[] = get_string('gradecanbechanged', 'assign'); } if (!$this->is_downloading() && $this->hasgrade) { // We have to call this column userid so we can use userid as a default sortable column. $columns[] = 'userid'; $headers[] = get_string('edit'); } // Submission plugins. if ($assignment->is_any_submission_plugin_enabled()) { $columns[] = 'timesubmitted'; $headers[] = get_string('lastmodifiedsubmission', 'assign'); foreach ($this->assignment->get_submission_plugins() as $plugin) { if ($this->is_downloading()) { if ($plugin->is_visible() && $plugin->is_enabled()) { foreach ($plugin->get_editor_fields() as $field => $description) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin, $field); $columns[] = $index; $headers[] = $plugin->get_name(); } } } else { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin); $columns[] = $index; $headers[] = $plugin->get_name(); } } } } // Time marked. $columns[] = 'timemarked'; $headers[] = get_string('lastmodifiedgrade', 'assign'); // Feedback plugins. foreach ($this->assignment->get_feedback_plugins() as $plugin) { if ($this->is_downloading()) { if ($plugin->is_visible() && $plugin->is_enabled()) { foreach ($plugin->get_editor_fields() as $field => $description) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin, $field); $columns[] = $index; $headers[] = $description; } } } else { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin); $columns[] = $index; $headers[] = $plugin->get_name(); } } } // Exclude 'Final grade' column in downloaded grading worksheets. if (!$this->is_downloading()) { // Final grade. $columns[] = 'finalgrade'; $headers[] = get_string('finalgrade', 'grades'); } // Load the grading info for all users. $this->gradinginfo = grade_get_grades($this->assignment->get_course()->id, 'mod', 'assign', $this->assignment->get_instance()->id, $users); if (!empty($CFG->enableoutcomes) && !empty($this->gradinginfo->outcomes)) { $columns[] = 'outcomes'; $headers[] = get_string('outcomes', 'grades'); } // Set the columns. $this->define_columns($columns); $this->define_headers($headers); foreach ($extrauserfields as $extrafield) { $this->column_class($extrafield, $extrafield); } $this->no_sorting('recordid'); $this->no_sorting('finalgrade'); $this->no_sorting('userid'); $this->no_sorting('select'); $this->no_sorting('outcomes'); if ($assignment->get_instance()->teamsubmission) { $this->no_sorting('team'); } $plugincolumnindex = 0; foreach ($this->assignment->get_submission_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $submissionpluginindex = 'plugin' . $plugincolumnindex++; $this->no_sorting($submissionpluginindex); } } foreach ($this->assignment->get_feedback_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $feedbackpluginindex = 'plugin' . $plugincolumnindex++; $this->no_sorting($feedbackpluginindex); } } // When there is no data we still want the column headers printed in the csv file. if ($this->is_downloading()) { $this->start_output(); } }
/** * Format a column of data for display. * * @param stdClass $row * @return string */ public function col_userid(stdClass $row) { global $USER; $edit = ''; $actions = array(); $urlparams = array('id' => $this->assignment->get_course_module()->id, 'rownum' => 0, 'action' => 'grader'); if ($this->assignment->is_blind_marking()) { $urlparams['blindid'] = $this->assignment->get_uniqueid_for_user($row->userid); } else { $urlparams['userid'] = $row->userid; } $url = new moodle_url('/mod/assign/view.php', $urlparams); $noimage = null; if (!$row->grade) { $description = get_string('grade'); } else { $description = get_string('updategrade', 'assign'); } $actions['grade'] = new action_menu_link_secondary($url, $noimage, $description); // Everything we need is in the row. $submission = $row; $flags = $row; if ($this->assignment->get_instance()->teamsubmission) { // Use the cache for this. $submission = false; $group = false; $this->get_group_and_submission($row->id, $group, $submission, -1); } $submissionsopen = $this->assignment->submissions_open($row->id, true, $submission, $flags, $this->gradinginfo); $caneditsubmission = $this->assignment->can_edit_submission($row->id, $USER->id); // Hide for offline assignments. if ($this->assignment->is_any_submission_plugin_enabled()) { if (!$row->status || $row->status == ASSIGN_SUBMISSION_STATUS_DRAFT || !$this->assignment->get_instance()->submissiondrafts) { if (!$row->locked) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'lock', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('preventsubmissionsshort', 'assign'); $actions['lock'] = new action_menu_link_secondary($url, $noimage, $description); } else { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'unlock', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('allowsubmissionsshort', 'assign'); $actions['unlock'] = new action_menu_link_secondary($url, $noimage, $description); } } if ($submissionsopen && $USER->id != $row->id && $caneditsubmission) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'editsubmission', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('editsubmission', 'assign'); $actions['editsubmission'] = new action_menu_link_secondary($url, $noimage, $description); } } if (($this->assignment->get_instance()->duedate || $this->assignment->get_instance()->cutoffdate) && $this->hasgrantextension) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'grantextension', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('grantextension', 'assign'); $actions['grantextension'] = new action_menu_link_secondary($url, $noimage, $description); } if ($row->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED && $this->assignment->get_instance()->submissiondrafts) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'reverttodraft', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('reverttodraftshort', 'assign'); $actions['reverttodraft'] = new action_menu_link_secondary($url, $noimage, $description); } if ($row->status == ASSIGN_SUBMISSION_STATUS_DRAFT && $this->assignment->get_instance()->submissiondrafts && $caneditsubmission && $submissionsopen && $row->id != $USER->id) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'submitotherforgrading', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('submitforgrading', 'assign'); $actions['submitforgrading'] = new action_menu_link_secondary($url, $noimage, $description); } $ismanual = $this->assignment->get_instance()->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL; $hassubmission = !empty($row->status); $notreopened = $hassubmission && $row->status != ASSIGN_SUBMISSION_STATUS_REOPENED; $isunlimited = $this->assignment->get_instance()->maxattempts == ASSIGN_UNLIMITED_ATTEMPTS; $hasattempts = $isunlimited || $row->attemptnumber < $this->assignment->get_instance()->maxattempts - 1; if ($ismanual && $hassubmission && $notreopened && $hasattempts) { $urlparams = array('id' => $this->assignment->get_course_module()->id, 'userid' => $row->id, 'action' => 'addattempt', 'sesskey' => sesskey(), 'page' => $this->currpage); $url = new moodle_url('/mod/assign/view.php', $urlparams); $description = get_string('addattempt', 'assign'); $actions['addattempt'] = new action_menu_link_secondary($url, $noimage, $description); } $menu = new action_menu(); $menu->set_owner_selector('.gradingtable-actionmenu'); $menu->set_alignment(action_menu::TL, action_menu::BL); $menu->set_constraint('.gradingtable > .no-overflow'); $menu->set_menu_trigger(get_string('edit')); foreach ($actions as $action) { $menu->add($action); } // Prioritise the menu ahead of all other actions. $menu->prioritise = true; $edit .= $this->output->render($menu); return $edit; }
/** * Print recent activity from all assignments in a given course * * This is used by the recent activity block * @param mixed $course the course to print activity for * @param bool $viewfullnames boolean to determine whether to show full names or not * @param int $timestart the time the rendering started * @return bool true if activity was printed, false otherwise. */ function assign_print_recent_activity($course, $viewfullnames, $timestart) { global $CFG, $USER, $DB, $OUTPUT; require_once $CFG->dirroot . '/mod/assign/locallib.php'; // Do not use log table if possible, it may be huge. $dbparams = array($timestart, $course->id, 'assign', ASSIGN_SUBMISSION_STATUS_SUBMITTED); $namefields = user_picture::fields('u', null, 'userid'); if (!($submissions = $DB->get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, um.id as recordid,\n {$namefields}\n FROM {assign_submission} asb\n JOIN {assign} a ON a.id = asb.assignment\n JOIN {course_modules} cm ON cm.instance = a.id\n JOIN {modules} md ON md.id = cm.module\n JOIN {user} u ON u.id = asb.userid\n LEFT JOIN {assign_user_mapping} um ON um.userid = u.id AND um.assignment = a.id\n WHERE asb.timemodified > ? AND\n asb.latest = 1 AND\n a.course = ? AND\n md.name = ? AND\n asb.status = ?\n ORDER BY asb.timemodified ASC", $dbparams))) { return false; } $modinfo = get_fast_modinfo($course); $show = array(); $grader = array(); $showrecentsubmissions = get_config('assign', 'showrecentsubmissions'); foreach ($submissions as $submission) { if (!array_key_exists($submission->cmid, $modinfo->get_cms())) { continue; } $cm = $modinfo->get_cm($submission->cmid); if (!$cm->uservisible) { continue; } if ($submission->userid == $USER->id) { $show[] = $submission; continue; } $context = context_module::instance($submission->cmid); // The act of submitting of assignment may be considered private - // only graders will see it if specified. if (empty($showrecentsubmissions)) { if (!array_key_exists($cm->id, $grader)) { $grader[$cm->id] = has_capability('moodle/grade:viewall', $context); } if (!$grader[$cm->id]) { continue; } } $groupmode = groups_get_activity_groupmode($cm, $course); if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) { if (isguestuser()) { // Shortcut - guest user does not belong into any group. continue; } // This will be slow - show only users that share group with me in this cm. if (!$modinfo->get_groups($cm->groupingid)) { continue; } $usersgroups = groups_get_all_groups($course->id, $submission->userid, $cm->groupingid); if (is_array($usersgroups)) { $usersgroups = array_keys($usersgroups); $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid)); if (empty($intersect)) { continue; } } } $show[] = $submission; } if (empty($show)) { return false; } echo $OUTPUT->heading(get_string('newsubmissions', 'assign') . ':', 3); foreach ($show as $submission) { $cm = $modinfo->get_cm($submission->cmid); $context = context_module::instance($submission->cmid); $assign = new assign($context, $cm, $cm->course); $link = $CFG->wwwroot . '/mod/assign/view.php?id=' . $cm->id; // Obscure first and last name if blind marking enabled. if ($assign->is_blind_marking()) { $submission->firstname = get_string('participant', 'mod_assign'); if (empty($submission->recordid)) { $submission->recordid = $assign->get_uniqueid_for_user($submission->userid); } $submission->lastname = $submission->recordid; } print_recent_activity_note($submission->timemodified, $submission, $cm->name, $link, false, $viewfullnames); } return true; }
/** * Callback called by comment::get_comments() and comment::add(). Gives an opportunity to enforce blind-marking. * * @param array $comments * @param stdClass $options * @return array * @throws comment_exception */ function assignsubmission_comments_comment_display($comments, $options) { global $CFG, $DB, $USER; if ($options->commentarea != 'submission_comments' && $options->commentarea != 'submission_comments_upgrade') { throw new comment_exception('invalidcommentarea'); } if (!($submission = $DB->get_record('assign_submission', array('id' => $options->itemid)))) { throw new comment_exception('invalidcommentitemid'); } $context = $options->context; $cm = $options->cm; $course = $options->courseid; require_once $CFG->dirroot . '/mod/assign/locallib.php'; $assignment = new assign($context, $cm, $course); if ($assignment->get_instance()->id != $submission->assignment) { throw new comment_exception('invalidcontext'); } if ($assignment->is_blind_marking() && !empty($comments)) { // Blind marking is being used, may need to map unique anonymous ids to the comments. $usermappings = array(); $hiddenuserstr = trim(get_string('hiddenuser', 'assign')); $guestuser = guest_user(); foreach ($comments as $comment) { // Anonymize the comments. if (empty($usermappings[$comment->userid])) { // The blind-marking information for this commenter has not been generated; do so now. $anonid = $assignment->get_uniqueid_for_user($comment->userid); $commenter = new stdClass(); $commenter->firstname = $hiddenuserstr; $commenter->lastname = $anonid; $commenter->picture = 0; $commenter->id = $guestuser->id; $commenter->email = $guestuser->email; $commenter->imagealt = $guestuser->imagealt; // Temporarily store blind-marking information for use in later comments if necessary. $usermappings[$comment->userid]->fullname = fullname($commenter); $usermappings[$comment->userid]->avatar = $assignment->get_renderer()->user_picture($commenter, array('size' => 18, 'link' => false)); } // Set blind-marking information for this comment. $comment->fullname = $usermappings[$comment->userid]->fullname; $comment->avatar = $usermappings[$comment->userid]->avatar; $comment->profileurl = null; } } return $comments; }
/** * Test reveal_identities */ public function test_reveal_identities() { global $DB, $USER; $this->resetAfterTest(true); // Create a course and assignment and users. $course = self::getDataGenerator()->create_course(); $teacher = self::getDataGenerator()->create_user(); $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); $this->setUser($teacher); $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); $params['course'] = $course->id; $params['submissiondrafts'] = 1; $params['sendnotifications'] = 0; $params['blindmarking'] = 1; $instance = $generator->create_instance($params); $cm = get_coursemodule_from_instance('assign', $instance->id); $context = context_module::instance($cm->id); $assign = new assign($context, $cm, $course); $student1 = self::getDataGenerator()->create_user(); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id); $this->setUser($student1); $this->setExpectedException('required_capability_exception'); $result = mod_assign_external::reveal_identities($instance->id); $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result); $this->assertEquals(1, count($result)); $this->assertEquals(true, $assign->is_blind_marking()); $this->setUser($teacher); $result = mod_assign_external::reveal_identities($instance->id); $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result); $this->assertEquals(0, count($result)); $this->assertEquals(false, $assign->is_blind_marking()); $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); $params['course'] = $course->id; $params['submissiondrafts'] = 1; $params['sendnotifications'] = 0; $params['blindmarking'] = 0; $instance = $generator->create_instance($params); $cm = get_coursemodule_from_instance('assign', $instance->id); $context = context_module::instance($cm->id); $assign = new assign($context, $cm, $course); $result = mod_assign_external::reveal_identities($instance->id); $result = external_api::clean_returnvalue(mod_assign_external::reveal_identities_returns(), $result); $this->assertEquals(1, count($result)); $this->assertEquals(false, $assign->is_blind_marking()); }
/** * overridden constructor keeps a reference to the assignment class that is displaying this table * * @param assign $assignment The assignment class * @param int $perpage how many per page * @param string $filter The current filter * @param int $rowoffset For showing a subsequent page of results * @param bool $quickgrading Is this table wrapped in a quickgrading form? */ public function __construct(assign $assignment, $perpage, $filter, $rowoffset, $quickgrading, $downloadfilename = null) { global $CFG, $PAGE, $DB; parent::__construct('mod_assign_grading'); $this->assignment = $assignment; foreach ($assignment->get_feedback_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled()) { foreach ($plugin->get_grading_batch_operations() as $action => $description) { if (empty($this->plugingradingbatchoperations)) { $this->plugingradingbatchoperations[$plugin->get_type()] = array(); } $this->plugingradingbatchoperations[$plugin->get_type()][$action] = $description; } } } $this->perpage = $perpage; $this->quickgrading = $quickgrading; $this->output = $PAGE->get_renderer('mod_assign'); $this->define_baseurl(new moodle_url($CFG->wwwroot . '/mod/assign/view.php', array('action'=>'grading', 'id'=>$assignment->get_course_module()->id))); // do some business - then set the sql $currentgroup = groups_get_activity_group($assignment->get_course_module(), true); if ($rowoffset) { $this->rownum = $rowoffset - 1; } $users = array_keys( $assignment->list_participants($currentgroup, true)); if (count($users) == 0) { // insert a record that will never match to the sql is still valid. $users[] = -1; } $params = array(); $params['assignmentid1'] = (int)$this->assignment->get_instance()->id; $params['assignmentid2'] = (int)$this->assignment->get_instance()->id; $fields = user_picture::fields('u') . ', '; $fields .= 'u.id as userid, '; $fields .= 's.status as status, '; $fields .= 's.id as submissionid, '; $fields .= 's.timecreated as firstsubmission, '; $fields .= 's.timemodified as timesubmitted, '; $fields .= 'g.id as gradeid, '; $fields .= 'g.grade as grade, '; $fields .= 'g.timemodified as timemarked, '; $fields .= 'g.timecreated as firstmarked, '; $fields .= 'g.mailed as mailed, '; $fields .= 'g.locked as locked, '; $fields .= 'g.extensionduedate as extensionduedate'; $from = '{user} u LEFT JOIN {assign_submission} s ON u.id = s.userid AND s.assignment = :assignmentid1' . ' LEFT JOIN {assign_grades} g ON u.id = g.userid AND g.assignment = :assignmentid2'; $userparams = array(); $userindex = 0; list($userwhere, $userparams) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED, 'user'); $where = 'u.id ' . $userwhere; $params = array_merge($params, $userparams); if ($filter == ASSIGN_FILTER_SUBMITTED) { $where .= ' AND s.timecreated > 0 '; } if ($filter == ASSIGN_FILTER_REQUIRE_GRADING) { $where .= ' AND (s.timemodified > g.timemodified OR (s.timemodified IS NOT NULL AND g.timemodified IS NULL))'; } if (strpos($filter, ASSIGN_FILTER_SINGLE_USER) === 0) { $userfilter = (int) array_pop(explode('=', $filter)); $where .= ' AND (u.id = :userid)'; $params['userid'] = $userfilter; } $this->set_sql($fields, $from, $where, $params); if ($downloadfilename) { $this->is_downloading('csv', $downloadfilename); } $columns = array(); $headers = array(); // Select. if (!$this->is_downloading()) { $columns[] = 'select'; $headers[] = get_string('select') . '<div class="selectall"><label class="accesshide" for="selectall">' . get_string('selectall') . '</label> <input type="checkbox" id="selectall" name="selectall" title="' . get_string('selectall') . '"/></div>'; } // User picture. if (!$this->assignment->is_blind_marking()) { if (!$this->is_downloading()) { $columns[] = 'picture'; $headers[] = get_string('pictureofuser'); } else { $columns[] = 'recordid'; $headers[] = get_string('recordid', 'assign'); } // Fullname. $columns[] = 'fullname'; $headers[] = get_string('fullname'); } else { // Record ID. $columns[] = 'recordid'; $headers[] = get_string('recordid', 'assign'); } // Submission status if ($assignment->is_any_submission_plugin_enabled()) { $columns[] = 'status'; $headers[] = get_string('status'); } // Team submission columns if ($assignment->get_instance()->teamsubmission) { $columns[] = 'team'; $headers[] = get_string('submissionteam', 'assign'); $columns[] = 'teamstatus'; $headers[] = get_string('teamsubmissionstatus', 'assign'); } // Grade $columns[] = 'grade'; $headers[] = get_string('grade'); if ($this->is_downloading()) { if ($this->assignment->get_instance()->grade >= 0) { $columns[] = 'grademax'; $headers[] = get_string('maxgrade', 'assign'); } else { // This is a custom scale. $columns[] = 'scale'; $headers[] = get_string('scale', 'assign'); } } if (!$this->is_downloading()) { // We have to call this column userid so we can use userid as a default sortable column. $columns[] = 'userid'; $headers[] = get_string('edit'); } // Submission plugins if ($assignment->is_any_submission_plugin_enabled()) { $columns[] = 'timesubmitted'; $headers[] = get_string('lastmodifiedsubmission', 'assign'); foreach ($this->assignment->get_submission_plugins() as $plugin) { if ($this->is_downloading()) { if ($plugin->is_visible() && $plugin->is_enabled()) { foreach ($plugin->get_editor_fields() as $field => $description) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin, $field); $columns[] = $index; $headers[] = $plugin->get_name(); } } } else { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin); $columns[] = $index; $headers[] = $plugin->get_name(); } } } } // time marked $columns[] = 'timemarked'; $headers[] = get_string('lastmodifiedgrade', 'assign'); // Feedback plugins foreach ($this->assignment->get_feedback_plugins() as $plugin) { if ($this->is_downloading()) { if ($plugin->is_visible() && $plugin->is_enabled()) { foreach ($plugin->get_editor_fields() as $field => $description) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin, $field); $columns[] = $index; $headers[] = $description; } } } else if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $index = 'plugin' . count($this->plugincache); $this->plugincache[$index] = array($plugin); $columns[] = $index; $headers[] = $plugin->get_name(); } } // Exclude 'Final grade' column in downloaded grading worksheets. if (!$this->is_downloading()) { // Final grade. $columns[] = 'finalgrade'; $headers[] = get_string('finalgrade', 'grades'); } // load the grading info for all users $this->gradinginfo = grade_get_grades($this->assignment->get_course()->id, 'mod', 'assign', $this->assignment->get_instance()->id, $users); $this->hasgrantextension = has_capability('mod/assign:grantextension', $this->assignment->get_context()); if (!empty($CFG->enableoutcomes) && !empty($this->gradinginfo->outcomes)) { $columns[] = 'outcomes'; $headers[] = get_string('outcomes', 'grades'); } // set the columns $this->define_columns($columns); $this->define_headers($headers); // We require at least one unique column for the sort. $this->sortable(true, 'userid'); $this->no_sorting('recordid'); $this->no_sorting('finalgrade'); $this->no_sorting('userid'); $this->no_sorting('select'); $this->no_sorting('outcomes'); if ($assignment->get_instance()->teamsubmission) { $this->no_sorting('team'); $this->no_sorting('teamstatus'); } $plugincolumnindex = 0; foreach ($this->assignment->get_submission_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $submissionpluginindex = 'plugin' . $plugincolumnindex++; $this->no_sorting($submissionpluginindex); } } foreach ($this->assignment->get_feedback_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->has_user_summary()) { $feedbackpluginindex = 'plugin' . $plugincolumnindex++; $this->no_sorting($feedbackpluginindex); } } // When there is no data we still want the column headers printed in the csv file. if ($this->is_downloading()) { $this->start_output(); } }
/** * Get the user participating in the given assignment. An error with code 'usernotincourse' * is thrown is the user isn't a participant of the given assignment. * * @param int $assignid the assign instance id * @param int $userid the user id * @param bool $embeduser return user details (only applicable if not blind marking) * @return array of warnings and status result * @since Moodle 3.1 * @throws moodle_exception */ public static function get_participant($assignid, $userid, $embeduser) { global $DB, $CFG; require_once $CFG->dirroot . "/mod/assign/locallib.php"; require_once $CFG->dirroot . "/user/lib.php"; $params = self::validate_parameters(self::get_participant_parameters(), array('assignid' => $assignid, 'userid' => $userid, 'embeduser' => $embeduser)); // Request and permission validation. $assign = $DB->get_record('assign', array('id' => $params['assignid']), 'id', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($assign, 'assign'); $context = context_module::instance($cm->id); self::validate_context($context); $assign = new assign($context, null, null); $assign->require_view_grades(); $participant = $assign->get_participant($params['userid']); if (!$participant) { // No participant found so we can return early. throw new moodle_exception('usernotincourse'); } $return = array('id' => $participant->id, 'fullname' => $participant->fullname, 'submitted' => $participant->submitted, 'requiregrading' => $participant->requiregrading, 'blindmarking' => $assign->is_blind_marking()); if (!empty($participant->groupid)) { $return['groupid'] = $participant->groupid; } if (!empty($participant->groupname)) { $return['groupname'] = $participant->groupname; } // Skip the expensive lookup of user detail if we're blind marking or the caller // hasn't asked for user details to be embedded. if (!$assign->is_blind_marking() && $embeduser) { $return['user'] = user_get_user_details($participant, $course); } return $return; }