/** * overridden constructor keeps a reference to the setaskment class that is displaying this table * * @param setask $setaskment The setaskment 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(setask $setaskment, $perpage, $filter, $rowoffset, $quickgrading, $downloadfilename = null) { global $CFG, $PAGE, $DB, $USER; parent::__construct('mod_setask_grading'); $this->is_persistent(true); $this->setaskment = $setaskment; // Check permissions up front. $this->hasgrantextension = has_capability('mod/setask:grantextension', $this->setaskment->get_context()); $this->hasgrade = $this->setaskment->can_grade(); // Check if we have the elevated view capablities to see the blind details. $this->hasviewblind = has_capability('mod/setask:viewblinddetails', $this->setaskment->get_context()); foreach ($setaskment->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_setask'); $urlparams = array('action' => 'grading', 'id' => $setaskment->get_course_module()->id); $url = new moodle_url($CFG->wwwroot . '/mod/setask/view.php', $urlparams); $this->define_baseurl($url); // Do some business - then set the sql. $currentgroup = groups_get_activity_group($setaskment->get_course_module(), true); if ($rowoffset) { $this->rownum = $rowoffset - 1; } $users = array_keys($setaskment->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['setaskmentid1'] = (int) $this->setaskment->get_instance()->id; $params['setaskmentid2'] = (int) $this->setaskment->get_instance()->id; $params['setaskmentid3'] = (int) $this->setaskment->get_instance()->id; $extrauserfields = get_extra_user_fields($this->setaskment->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 {setask_submission} s ON u.id = s.userid AND s.setaskment = :setaskmentid1 AND s.latest = 1 LEFT JOIN {setask_grades} g ON u.id = g.userid AND g.setaskment = :setaskmentid2 '; // For group submissions we don't immediately create an entry in the setask_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->setaskment->get_instance()->teamsubmission) { $params['setaskmentid4'] = (int) $this->setaskment->get_instance()->id; $grademaxattempt = 'SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt FROM {setask_grades} mxg WHERE mxg.setaskment = :setaskmentid4 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 {setask_user_flags} uf ON u.id = uf.userid AND uf.setaskment = :setaskmentid3'; $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->setaskment->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->setaskment->get_instance()->markingworkflow && $this->setaskment->get_instance()->markingallocation) { if (has_capability('mod/setask:manageallocations', $this->setaskment->get_context())) { // Check to see if marker filter is set. $markerfilter = (int) get_user_preferences('setask_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->setaskment->get_instance()->markingworkflow) { $workflowstates = $this->setaskment->get_marking_workflow_states_for_current_user(); if (!empty($workflowstates)) { $workflowfilter = get_user_preferences('setask_workflowfilter', ''); if ($workflowfilter == ASSIGN_MARKING_WORKFLOW_STATE_NOTMARKED) { $where .= ' AND (uf.workflowstate = :workflowstate OR uf.workflowstate IS NULL OR ' . $DB->sql_isempty('setask_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->setaskment->is_blind_marking()) { if (!$this->is_downloading()) { $columns[] = 'picture'; $headers[] = get_string('pictureofuser'); } else { $columns[] = 'recordid'; $headers[] = get_string('recordid', 'setask'); } // 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', 'setask'); } // Submission status. $columns[] = 'status'; $headers[] = get_string('status', 'setask'); // Team submission columns. if ($setaskment->get_instance()->teamsubmission) { $columns[] = 'team'; $headers[] = get_string('submissionteam', 'setask'); } // Allocated marker. if ($this->setaskment->get_instance()->markingworkflow && $this->setaskment->get_instance()->markingallocation && has_capability('mod/setask:manageallocations', $this->setaskment->get_context())) { // Add a column for the allocated marker. $columns[] = 'allocatedmarker'; $headers[] = get_string('marker', 'setask'); } // Grade. $columns[] = 'grade'; $headers[] = get_string('grade'); if ($this->is_downloading()) { if ($this->setaskment->get_instance()->grade >= 0) { $columns[] = 'grademax'; $headers[] = get_string('maxgrade', 'setask'); } else { // This is a custom scale. $columns[] = 'scale'; $headers[] = get_string('scale', 'setask'); } if ($this->setaskment->get_instance()->markingworkflow) { // Add a column for the marking workflow state. $columns[] = 'workflowstate'; $headers[] = get_string('markingworkflowstate', 'setask'); } // Add a column for the list of valid marking workflow states. $columns[] = 'gradecanbechanged'; $headers[] = get_string('gradecanbechanged', 'setask'); } 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 ($setaskment->is_any_submission_plugin_enabled()) { $columns[] = 'timesubmitted'; $headers[] = get_string('lastmodifiedsubmission', 'setask'); foreach ($this->setaskment->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', 'setask'); // Feedback plugins. foreach ($this->setaskment->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->setaskment->get_course()->id, 'mod', 'setask', $this->setaskment->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); } // 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 ($setaskment->get_instance()->teamsubmission) { $this->no_sorting('team'); } $plugincolumnindex = 0; foreach ($this->setaskment->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->setaskment->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(); } }