2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * This page handles listing of quiz overrides
21 * @copyright 2010 Matt Petro
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 use mod_quiz\quiz_settings
;
27 require_once(__DIR__
. '/../../config.php');
28 require_once($CFG->dirroot
.'/mod/quiz/lib.php');
29 require_once($CFG->dirroot
.'/mod/quiz/locallib.php');
31 $cmid = required_param('cmid', PARAM_INT
);
32 $mode = optional_param('mode', '', PARAM_ALPHA
); // One of 'user' or 'group', default is 'group'.
34 $quizobj = quiz_settings
::create_for_cmid($cmid);
35 $quiz = $quizobj->get_quiz();
36 $cm = $quizobj->get_cm();
37 $course = $quizobj->get_course();
38 $context = $quizobj->get_context();
40 require_login($course, false, $cm);
42 // Check the user has the required capabilities to list overrides.
43 $canedit = has_capability('mod/quiz:manageoverrides', $context);
45 require_capability('mod/quiz:viewoverrides', $context);
48 $quizgroupmode = groups_get_activity_groupmode($cm);
49 $showallgroups = ($quizgroupmode == NOGROUPS
) ||
has_capability('moodle/site:accessallgroups', $context);
51 // Get the course groups that the current user can access.
52 $groups = $showallgroups ?
groups_get_all_groups($cm->course
) : groups_get_activity_allowed_groups($cm);
54 // Default mode is "group", unless there are no groups.
55 if ($mode != "user" and $mode != "group") {
56 if (!empty($groups)) {
62 $groupmode = ($mode == "group");
64 $url = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id
, 'mode' => $mode]);
66 $title = get_string('overridesforquiz', 'quiz',
67 format_string($quiz->name
, true, ['context' => $context]));
69 $PAGE->set_pagelayout('admin');
70 $PAGE->add_body_class('limitedwidth');
71 $PAGE->set_title($title);
72 $PAGE->set_heading($course->fullname
);
73 $PAGE->activityheader
->disable();
75 // Activate the secondary nav tab.
76 $PAGE->set_secondary_active_tab("mod_quiz_useroverrides");
78 // Delete orphaned group overrides.
80 FROM {quiz_overrides} o
81 LEFT JOIN {groups} g ON o.groupid = g.id
82 WHERE o.groupid IS NOT NULL
85 $params = [$quiz->id
];
86 $orphaned = $DB->get_records_sql($sql, $params);
87 if (!empty($orphaned)) {
88 $DB->delete_records_list('quiz_overrides', 'id', array_keys($orphaned));
95 // Fetch all overrides.
97 $headers[] = get_string('group');
98 // To filter the result by the list of groups that the current user has access to.
100 $params = ['quizid' => $quiz->id
];
101 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($groups), SQL_PARAMS_NAMED
);
102 $params +
= $inparams;
104 $sql = "SELECT o.*, g.name
105 FROM {quiz_overrides} o
106 JOIN {groups} g ON o.groupid = g.id
107 WHERE o.quiz = :quizid AND g.id $insql
110 $overrides = $DB->get_records_sql($sql, $params);
115 $colclasses[] = 'colname';
116 $headers[] = get_string('user');
117 $userfieldsapi = \core_user\fields
::for_identity($context)->with_name()->with_userpic();
118 $extrauserfields = $userfieldsapi->get_required_fields([\core_user\fields
::PURPOSE_IDENTITY
]);
119 $userfieldssql = $userfieldsapi->get_sql('u', true, '', 'userid', false);
120 foreach ($extrauserfields as $field) {
121 $colclasses[] = 'col' . $field;
122 $headers[] = \core_user\fields
::get_display_name($field);
125 list($sort, $params) = users_order_by_sql('u', null, $context, $extrauserfields);
126 $params['quizid'] = $quiz->id
;
128 if ($showallgroups) {
132 } else if ($groups) {
133 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($groups), SQL_PARAMS_NAMED
);
134 $groupsjoin = 'JOIN {groups_members} gm ON u.id = gm.userid';
135 $groupswhere = ' AND gm.groupid ' . $insql;
136 $params +
= $inparams;
139 // User cannot see any data.
141 $groupswhere = ' AND 1 = 2';
144 $overrides = $DB->get_records_sql("
145 SELECT o.*, {$userfieldssql->selects}
146 FROM {quiz_overrides} o
147 JOIN {user} u ON o.userid = u.id
148 {$userfieldssql->joins}
150 WHERE o.quiz = :quizid
153 ", array_merge($params, $userfieldssql->params
));
157 $table = new html_table();
158 $table->head
= $headers;
159 $table->colclasses
= $colclasses;
160 $table->headspan
= array_fill(0, count($headers), 1);
162 $table->head
[] = get_string('overrides', 'quiz');
163 $table->colclasses
[] = 'colsetting';
164 $table->colclasses
[] = 'colvalue';
165 $table->headspan
[] = 2;
168 $table->head
[] = get_string('action');
169 $table->colclasses
[] = 'colaction';
170 $table->headspan
[] = 1;
172 $userurl = new moodle_url('/user/view.php', []);
173 $groupurl = new moodle_url('/group/overview.php', ['id' => $cm->course
]);
175 $overridedeleteurl = new moodle_url('/mod/quiz/overridedelete.php');
176 $overrideediturl = new moodle_url('/mod/quiz/overrideedit.php');
178 $hasinactive = false; // Whether there are any inactive overrides.
180 foreach ($overrides as $override) {
182 // Check if this override is active.
185 if (!has_capability('mod/quiz:attempt', $context, $override->userid
)) {
186 // User not allowed to take the quiz.
188 } else if (!\core_availability\info_module
::is_user_visible($cm, $override->userid
)) {
189 // User cannot access the module.
197 // Prepare the information about which settings are overridden.
202 if (isset($override->timeopen
)) {
203 $fields[] = get_string('quizopens', 'quiz');
204 $values[] = $override->timeopen
> 0 ?
205 userdate($override->timeopen
) : get_string('noopen', 'quiz');
208 if (isset($override->timeclose
)) {
209 $fields[] = get_string('quizcloses', 'quiz');
210 $values[] = $override->timeclose
> 0 ?
211 userdate($override->timeclose
) : get_string('noclose', 'quiz');
214 if (isset($override->timelimit
)) {
215 $fields[] = get_string('timelimit', 'quiz');
216 $values[] = $override->timelimit
> 0 ?
217 format_time($override->timelimit
) : get_string('none', 'quiz');
219 // Format number of attempts.
220 if (isset($override->attempts
)) {
221 $fields[] = get_string('attempts', 'quiz');
222 $values[] = $override->attempts
> 0 ?
223 $override->attempts
: get_string('unlimited');
226 if (isset($override->password
)) {
227 $fields[] = get_string('requirepassword', 'quiz');
228 $values[] = $override->password
!== '' ?
229 get_string('enabled', 'quiz') : get_string('none', 'quiz');
232 // Prepare the information about who this override applies to.
233 $extranamebit = $active ?
'' : '*';
236 $groupcell = new html_table_cell();
237 $groupcell->rowspan
= count($fields);
238 $groupcell->text
= html_writer
::link(new moodle_url($groupurl, ['group' => $override->groupid
]),
239 format_string($override->name
, true, ['context' => $context]) . $extranamebit);
240 $usercells[] = $groupcell;
242 $usercell = new html_table_cell();
243 $usercell->rowspan
= count($fields);
244 $usercell->text
= html_writer
::link(new moodle_url($userurl, ['id' => $override->userid
]),
245 fullname($override) . $extranamebit);
246 $usercells[] = $usercell;
248 foreach ($extrauserfields as $field) {
249 $usercell = new html_table_cell();
250 $usercell->rowspan
= count($fields);
251 $usercell->text
= s($override->$field);
252 $usercells[] = $usercell;
256 // Prepare the actions.
262 $editurlstr = $overrideediturl->out(true, ['id' => $override->id
]);
263 $iconstr = '<a title="' . get_string('edit') . '" href="' . $editurlstr . '">' .
264 $OUTPUT->pix_icon('t/edit', get_string('edit')) . '</a> ';
266 $copyurlstr = $overrideediturl->out(true,
267 ['id' => $override->id
, 'action' => 'duplicate']);
268 $iconstr .= '<a title="' . get_string('copy') . '" href="' . $copyurlstr . '">' .
269 $OUTPUT->pix_icon('t/copy', get_string('copy')) . '</a> ';
271 $deleteurlstr = $overridedeleteurl->out(true,
272 ['id' => $override->id
, 'sesskey' => sesskey()]);
273 $iconstr .= '<a title="' . get_string('delete') . '" href="' . $deleteurlstr . '">' .
274 $OUTPUT->pix_icon('t/delete', get_string('delete')) . '</a> ';
276 $actioncell = new html_table_cell();
277 $actioncell->rowspan
= count($fields);
278 $actioncell->text
= $iconstr;
281 // Add the data to the table.
282 for ($i = 0; $i < count($fields); ++
$i) {
283 $row = new html_table_row();
285 $row->attributes
['class'] = 'dimmed_text';
289 $row->cells
= $usercells;
292 $labelcell = new html_table_cell();
293 $labelcell->text
= $fields[$i];
294 $row->cells
[] = $labelcell;
295 $valuecell = new html_table_cell();
296 $valuecell->text
= $values[$i];
297 $row->cells
[] = $valuecell;
299 if ($canedit && $i == 0) {
300 $row->cells
[] = $actioncell;
303 $table->data
[] = $row;
307 // Work out what else needs to be displayed.
309 $warningmessage = '';
312 if (empty($groups)) {
313 // There are no groups.
314 $warningmessage = get_string('groupsnone', 'quiz');
318 // See if there are any students in the quiz.
319 if ($showallgroups) {
320 $users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id');
321 $nousermessage = get_string('usersnone', 'quiz');
322 } else if ($groups) {
323 $users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id', '', '', '', array_keys($groups));
324 $nousermessage = get_string('usersnone', 'quiz');
327 $nousermessage = get_string('groupsnone', 'quiz');
329 $info = new \core_availability\
info_module($cm);
330 $users = $info->filter_user_list($users);
333 // There are no students.
334 $warningmessage = $nousermessage;
340 // Tertiary navigation.
341 echo $OUTPUT->header();
342 $renderer = $PAGE->get_renderer('mod_quiz');
343 $tertiarynav = new \mod_quiz\output\
overrides_actions($cmid, $mode, $canedit, $addenabled);
344 echo $renderer->render($tertiarynav);
346 if ($mode === 'user') {
347 echo $OUTPUT->heading(get_string('useroverrides', 'quiz'));
349 echo $OUTPUT->heading(get_string('groupoverrides', 'quiz'));
352 // Output the table and button.
353 echo html_writer
::start_tag('div', ['id' => 'quizoverrides']);
354 if (count($table->data
)) {
355 echo html_writer
::table($table);
358 echo $OUTPUT->notification(get_string('overridesnoneforgroups', 'quiz'), 'info', false);
360 echo $OUTPUT->notification(get_string('overridesnoneforusers', 'quiz'), 'info', false);
364 echo $OUTPUT->notification(get_string('inactiveoverridehelp', 'quiz'), 'info', false);
367 if ($warningmessage) {
368 echo $OUTPUT->notification($warningmessage, 'error');
371 echo html_writer
::end_tag('div');
374 echo $OUTPUT->footer();