-
Bug
-
Resolution: Fixed
-
Minor
-
2.7.10, 2.8.9, 2.9.3, 3.0
-
MOODLE_27_STABLE, MOODLE_28_STABLE, MOODLE_29_STABLE, MOODLE_30_STABLE
-
MOODLE_28_STABLE, MOODLE_29_STABLE
-
MDL-51720-master -
We are having a problem with the sort order for Assignment (assign) View/Grade submissions function when used by a local, created role that allows a teaching assistant to edit course pages but not assign grades.
There is no problem when viewed as the editing Teacher role , but when viewed our T/A role, with 43 users, the first 40 display correctly but the last (5th) page does not
We have analyzed the problem and have suggested a fix below. We are using Moodle 2.7.3 (Build: 20141110), however the code for this is identical in the current version, Moodle 2.9.2.
=============================================
mod/assign/gradingtable.php
88 // Check permissions up front.
89 $this->hasgrantextension = has_capability('mod/assign:grantextension',
90 $this->assignment->get_context());
91 $this->hasgrade = $this->assignment->can_grade();
:
:
:
320 if (!$this->is_downloading() && $this->hasgrade) {
321 // We have to call this column userid so we can use userid as a default sortable column.
322 $columns[] = 'userid';
323 $headers[] = get_string('edit');
=============================================
According to line 320, when hasgrade == 0, the data is not sorted by userid. It seems that can_grade() contains the current value of mod/assign:grade
This following code thus generates different SQL for editingteacher and our T/A role:
=============================================
150 $submissionmaxattempt = 'SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
151 FROM
152 WHERE mxs.assignment = :assignmentid4 GROUP BY mxs.userid';
153 $grademaxattempt = 'SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt
154 FROM {assign_grades} mxg
155 WHERE mxg.assignment = :assignmentid5 GROUP BY mxg.userid';
156 $from = '{user} u
157 LEFT JOIN ( ' . $submissionmaxattempt . ' ) smx ON u.id = smx.userid
158 LEFT JOIN ( ' . $grademaxattempt . ' ) gmx ON u.id = gmx.userid
159 LEFT JOIN {assign_submission}
s ON
160 u.id = s.userid AND
161 s.assignment = :assignmentid1 AND
162 s.attemptnumber = smx.maxattempt
163 LEFT JOIN
g ON
164 u.id = g.userid AND
165 g.assignment = :assignmentid2 AND
166 g.attemptnumber = gmx.maxattempt
167 LEFT JOIN
uf ON u.id = uf.userid AND uf.assignment = :assignmentid3';
168
169 $userparams = array();
170 $userindex = 0;
171
172 list($userwhere, $userparams) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED, 'user');
173 $where = 'u.id ' . $userwhere;
174 $params = array_merge($params, $userparams);
=============================================
The difference comes in the secton after then "Where" clause causing differences in ORDER BY, LIMIT and OFFSET parameters.
***EditingTeacher
SELECT
~~~~
FROM mdl_user u
LEFT JOIN ( SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
FROM mdl_assign_submission mxs
WHERE mxs.assignment = $1 GROUP BY mxs.userid ) smx ON u.id = smx.userid
LEFT JOIN ( SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt
FROM mdl_assign_grades mxg
WHERE mxg.assignment = $2 GROUP BY mxg.userid ) gmx ON u.id = gmx.userid
LEFT JOIN mdl_assign_submission s ON
u.id = s.userid AND
s.assignment = $3 AND
s.attemptnumber = smx.maxattempt
LEFT JOIN mdl_assign_grades g ON
u.id = g.userid AND
g.assignment = $4 AND
g.attemptnumber = gmx.maxattempt
LEFT JOIN mdl_assign_user_flags uf ON u.id = uf.userid AND uf.assignment = $5
WHERE u.id IN (~~~~~
ORDER BY userid ASC LIMIT 10 OFFSET 50
***T/A Role ("mod/assign:grade"==0)
SELECT
~~~~
FROM mdl_user u
LEFT JOIN ( SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
FROM mdl_assign_submission mxs
WHERE mxs.assignment = $1 GROUP BY mxs.userid ) smx ON u.id = smx.userid
LEFT JOIN ( SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt
FROM mdl_assign_grades mxg
WHERE mxg.assignment = $2 GROUP BY mxg.userid ) gmx ON u.id = gmx.userid
LEFT JOIN mdl_assign_submission s ON
u.id = s.userid AND
s.assignment = $3 AND
s.attemptnumber = smx.maxattempt
LEFT JOIN mdl_assign_grades g ON
u.id = g.userid AND
g.assignment = $4 AND
g.attemptnumber = gmx.maxattempt
LEFT JOIN mdl_assign_user_flags uf ON u.id = uf.userid AND uf.assignment = $5
WHERE u.id IN (~~~~~
LIMIT 10 OFFSET 50
^^^^
As can be seen, the "ORDER BY userid" parameter is missin.
***FIX
It seems that the parameter "&& $this->hasgrade" is not needed for this function to work properly.
=============================================
mod/assign/gradingtable.php
320 //if (!$this->is_downloading() && $this->hasgrade) {
321 if (!$this->is_downloading()) {
322 // We have to call this column userid so we can use userid as a default sortable column.
323 $columns[] = 'userid';
324 $headers[] = get_string('edit');
=============================================