Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 page handles listing of quiz overrides 19 * 20 * @package mod_quiz 21 * @copyright 2010 Matt Petro 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 require_once(__DIR__ . '/../../config.php'); 26 require_once($CFG->dirroot.'/mod/quiz/lib.php'); 27 require_once($CFG->dirroot.'/mod/quiz/locallib.php'); 28 require_once($CFG->dirroot.'/mod/quiz/override_form.php'); 29 30 31 $cmid = required_param('cmid', PARAM_INT); 32 $mode = optional_param('mode', '', PARAM_ALPHA); // One of 'user' or 'group', default is 'group'. 33 34 list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'quiz'); 35 $quiz = $DB->get_record('quiz', ['id' => $cm->instance], '*', MUST_EXIST); 36 37 require_login($course, false, $cm); 38 39 $context = context_module::instance($cm->id); 40 41 // Check the user has the required capabilities to list overrides. 42 $canedit = has_capability('mod/quiz:manageoverrides', $context); 43 if (!$canedit) { 44 require_capability('mod/quiz:viewoverrides', $context); 45 } 46 47 $quizgroupmode = groups_get_activity_groupmode($cm); 48 $showallgroups = ($quizgroupmode == NOGROUPS) || has_capability('moodle/site:accessallgroups', $context); 49 50 // Get the course groups that the current user can access. 51 $groups = $showallgroups ? groups_get_all_groups($cm->course) : groups_get_activity_allowed_groups($cm); 52 53 // Default mode is "group", unless there are no groups. 54 if ($mode != "user" and $mode != "group") { 55 if (!empty($groups)) { 56 $mode = "group"; 57 } else { 58 $mode = "user"; 59 } 60 } 61 $groupmode = ($mode == "group"); 62 63 $url = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id, 'mode' => $mode]); 64 65 $title = get_string('overridesforquiz', 'quiz', 66 format_string($quiz->name, true, ['context' => $context])); 67 $PAGE->set_url($url); 68 $PAGE->set_pagelayout('admin'); 69 $PAGE->set_title($title); 70 $PAGE->set_heading($course->fullname); 71 72 // Delete orphaned group overrides. 73 $sql = 'SELECT o.id 74 FROM {quiz_overrides} o 75 LEFT JOIN {groups} g ON o.groupid = g.id 76 WHERE o.groupid IS NOT NULL 77 AND g.id IS NULL 78 AND o.quiz = ?'; 79 $params = [$quiz->id]; 80 $orphaned = $DB->get_records_sql($sql, $params); 81 if (!empty($orphaned)) { 82 $DB->delete_records_list('quiz_overrides', 'id', array_keys($orphaned)); 83 } 84 85 $overrides = []; 86 $colclasses = []; 87 $headers = []; 88 89 // Fetch all overrides. 90 if ($groupmode) { 91 $headers[] = get_string('group'); 92 // To filter the result by the list of groups that the current user has access to. 93 if ($groups) { 94 $params = ['quizid' => $quiz->id]; 95 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($groups), SQL_PARAMS_NAMED); 96 $params += $inparams; 97 98 $sql = "SELECT o.*, g.name 99 FROM {quiz_overrides} o 100 JOIN {groups} g ON o.groupid = g.id 101 WHERE o.quiz = :quizid AND g.id $insql 102 ORDER BY g.name"; 103 104 $overrides = $DB->get_records_sql($sql, $params); 105 } 106 107 } else { 108 // User overrides. 109 $colclasses[] = 'colname'; 110 $headers[] = get_string('user'); 111 // TODO Does not support custom user profile fields (MDL-70456). 112 $userfieldsapi = \core_user\fields::for_identity($context, false)->with_name()->with_userpic(); 113 $extrauserfields = $userfieldsapi->get_required_fields([\core_user\fields::PURPOSE_IDENTITY]); 114 foreach ($extrauserfields as $field) { 115 $colclasses[] = 'col' . $field; 116 $headers[] = \core_user\fields::get_display_name($field); 117 } 118 119 list($sort, $params) = users_order_by_sql('u'); 120 $params['quizid'] = $quiz->id; 121 $userfields = $userfieldsapi->get_sql('u', true, '', 'userid', false)->selects; 122 123 if ($showallgroups) { 124 $groupsjoin = ''; 125 $groupswhere = ''; 126 127 } else if ($groups) { 128 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($groups), SQL_PARAMS_NAMED); 129 $groupsjoin = 'JOIN {groups_members} gm ON u.id = gm.userid'; 130 $groupswhere = ' AND gm.groupid ' . $insql; 131 $params += $inparams; 132 133 } else { 134 // User cannot see any data. 135 $groupsjoin = ''; 136 $groupswhere = ' AND 1 = 2'; 137 } 138 139 $overrides = $DB->get_records_sql(" 140 SELECT o.*, $userfields 141 FROM {quiz_overrides} o 142 JOIN {user} u ON o.userid = u.id 143 $groupsjoin 144 WHERE o.quiz = :quizid 145 $groupswhere 146 ORDER BY $sort 147 ", $params); 148 } 149 150 // Initialise table. 151 $table = new html_table(); 152 $table->head = $headers; 153 $table->colclasses = $colclasses; 154 $table->headspan = array_fill(0, count($headers), 1); 155 156 $table->head[] = get_string('overrides', 'quiz'); 157 $table->colclasses[] = 'colsetting'; 158 $table->colclasses[] = 'colvalue'; 159 $table->headspan[] = 2; 160 161 if ($canedit) { 162 $table->head[] = get_string('action'); 163 $table->colclasses[] = 'colaction'; 164 $table->headspan[] = 1; 165 } 166 $userurl = new moodle_url('/user/view.php', []); 167 $groupurl = new moodle_url('/group/overview.php', ['id' => $cm->course]); 168 169 $overridedeleteurl = new moodle_url('/mod/quiz/overridedelete.php'); 170 $overrideediturl = new moodle_url('/mod/quiz/overrideedit.php'); 171 172 $hasinactive = false; // Whether there are any inactive overrides. 173 174 foreach ($overrides as $override) { 175 176 // Check if this override is active. 177 $active = true; 178 if (!$groupmode) { 179 if (!has_capability('mod/quiz:attempt', $context, $override->userid)) { 180 // User not allowed to take the quiz. 181 $active = false; 182 } else if (!\core_availability\info_module::is_user_visible($cm, $override->userid)) { 183 // User cannot access the module. 184 $active = false; 185 } 186 } 187 if (!$active) { 188 $hasinactive = true; 189 } 190 191 // Prepare the information about which settings are overridden. 192 $fields = []; 193 $values = []; 194 195 // Format timeopen. 196 if (isset($override->timeopen)) { 197 $fields[] = get_string('quizopens', 'quiz'); 198 $values[] = $override->timeopen > 0 ? 199 userdate($override->timeopen) : get_string('noopen', 'quiz'); 200 } 201 // Format timeclose. 202 if (isset($override->timeclose)) { 203 $fields[] = get_string('quizcloses', 'quiz'); 204 $values[] = $override->timeclose > 0 ? 205 userdate($override->timeclose) : get_string('noclose', 'quiz'); 206 } 207 // Format timelimit. 208 if (isset($override->timelimit)) { 209 $fields[] = get_string('timelimit', 'quiz'); 210 $values[] = $override->timelimit > 0 ? 211 format_time($override->timelimit) : get_string('none', 'quiz'); 212 } 213 // Format number of attempts. 214 if (isset($override->attempts)) { 215 $fields[] = get_string('attempts', 'quiz'); 216 $values[] = $override->attempts > 0 ? 217 $override->attempts : get_string('unlimited'); 218 } 219 // Format password. 220 if (isset($override->password)) { 221 $fields[] = get_string('requirepassword', 'quiz'); 222 $values[] = $override->password !== '' ? 223 get_string('enabled', 'quiz') : get_string('none', 'quiz'); 224 } 225 226 // Prepare the information about who this override applies to. 227 $extranamebit = $active ? '' : '*'; 228 $usercells = []; 229 if ($groupmode) { 230 $groupcell = new html_table_cell(); 231 $groupcell->rowspan = count($fields); 232 $groupcell->text = html_writer::link(new moodle_url($groupurl, ['group' => $override->groupid]), 233 $override->name . $extranamebit); 234 $usercells[] = $groupcell; 235 } else { 236 $usercell = new html_table_cell(); 237 $usercell->rowspan = count($fields); 238 $usercell->text = html_writer::link(new moodle_url($userurl, ['id' => $override->userid]), 239 fullname($override) . $extranamebit); 240 $usercells[] = $usercell; 241 242 foreach ($extrauserfields as $field) { 243 $usercell = new html_table_cell(); 244 $usercell->rowspan = count($fields); 245 $usercell->text = s($override->$field); 246 $usercells[] = $usercell; 247 } 248 } 249 250 // Prepare the actions. 251 if ($canedit) { 252 // Icons. 253 $iconstr = ''; 254 255 // Edit. 256 $editurlstr = $overrideediturl->out(true, ['id' => $override->id]); 257 $iconstr = '<a title="' . get_string('edit') . '" href="' . $editurlstr . '">' . 258 $OUTPUT->pix_icon('t/edit', get_string('edit')) . '</a> '; 259 // Duplicate. 260 $copyurlstr = $overrideediturl->out(true, 261 ['id' => $override->id, 'action' => 'duplicate']); 262 $iconstr .= '<a title="' . get_string('copy') . '" href="' . $copyurlstr . '">' . 263 $OUTPUT->pix_icon('t/copy', get_string('copy')) . '</a> '; 264 // Delete. 265 $deleteurlstr = $overridedeleteurl->out(true, 266 ['id' => $override->id, 'sesskey' => sesskey()]); 267 $iconstr .= '<a title="' . get_string('delete') . '" href="' . $deleteurlstr . '">' . 268 $OUTPUT->pix_icon('t/delete', get_string('delete')) . '</a> '; 269 270 $actioncell = new html_table_cell(); 271 $actioncell->rowspan = count($fields); 272 $actioncell->text = $iconstr; 273 } 274 275 // Add the data to the table. 276 for ($i = 0; $i < count($fields); ++$i) { 277 $row = new html_table_row(); 278 if (!$active) { 279 $row->attributes['class'] = 'dimmed_text'; 280 } 281 282 if ($i == 0) { 283 $row->cells = $usercells; 284 } 285 286 $labelcell = new html_table_cell(); 287 $labelcell->text = $fields[$i]; 288 $row->cells[] = $labelcell; 289 $valuecell = new html_table_cell(); 290 $valuecell->text = $values[$i]; 291 $row->cells[] = $valuecell; 292 293 if ($canedit && $i == 0) { 294 $row->cells[] = $actioncell; 295 } 296 297 $table->data[] = $row; 298 } 299 } 300 301 // Display a list of overrides. 302 echo $OUTPUT->header(); 303 echo $OUTPUT->heading($title); 304 305 // Output the table and button. 306 echo html_writer::start_tag('div', ['id' => 'quizoverrides']); 307 if (count($table->data)) { 308 echo html_writer::table($table); 309 } else { 310 if ($groupmode) { 311 echo $OUTPUT->notification(get_string('overridesnoneforgroups', 'quiz'), 'info', false); 312 } else { 313 echo $OUTPUT->notification(get_string('overridesnoneforusers', 'quiz'), 'info', false); 314 } 315 } 316 if ($hasinactive) { 317 echo $OUTPUT->notification(get_string('inactiveoverridehelp', 'quiz'), 'info', false); 318 } 319 320 if ($canedit) { 321 echo html_writer::start_tag('div', ['class' => 'buttons']); 322 $options = []; 323 if ($groupmode) { 324 if (empty($groups)) { 325 // There are no groups. 326 echo $OUTPUT->notification(get_string('groupsnone', 'quiz'), 'error'); 327 $options['disabled'] = true; 328 } 329 echo $OUTPUT->single_button($overrideediturl->out(true, 330 ['action' => 'addgroup', 'cmid' => $cm->id]), 331 get_string('addnewgroupoverride', 'quiz'), 'post', $options); 332 } else { 333 $users = []; 334 // See if there are any students in the quiz. 335 if ($showallgroups) { 336 $users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id'); 337 $nousermessage = get_string('usersnone', 'quiz'); 338 } else if ($groups) { 339 $users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id', '', '', '', array_keys($groups)); 340 $nousermessage = get_string('usersnone', 'quiz'); 341 } else { 342 $nousermessage = get_string('groupsnone', 'quiz'); 343 } 344 $info = new \core_availability\info_module($cm); 345 $users = $info->filter_user_list($users); 346 347 if (empty($users)) { 348 // There are no students. 349 echo $OUTPUT->notification($nousermessage, 'error'); 350 $options['disabled'] = true; 351 } 352 echo $OUTPUT->single_button($overrideediturl->out(true, 353 ['action' => 'adduser', 'cmid' => $cm->id]), 354 get_string('addnewuseroverride', 'quiz'), 'get', $options); 355 } 356 echo html_writer::end_tag('div'); 357 } 358 359 echo html_writer::end_tag('div'); 360 361 // Finish the page. 362 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body