This commit is contained in:
Jun Pataleta 2020-12-16 23:01:28 +08:00
commit 037417af1d
10 changed files with 295 additions and 224 deletions

View File

@ -84,9 +84,10 @@ class notification implements \renderable, \templatable {
* Notification constructor.
*
* @param string $message the message to print out
* @param string $messagetype one of the NOTIFY_* constants..
* @param ?string $messagetype one of the NOTIFY_* constants..
* @param bool $closebutton Whether to show a close icon to remove the notification (default true).
*/
public function __construct($message, $messagetype = null) {
public function __construct($message, $messagetype = null, $closebutton = true) {
$this->message = $message;
if (empty($messagetype)) {
@ -94,6 +95,8 @@ class notification implements \renderable, \templatable {
}
$this->messagetype = $messagetype;
$this->closebutton = $closebutton;
}
/**

View File

@ -2875,10 +2875,11 @@ EOD;
* Note: \core\notification::add() may be more suitable for your usage.
*
* @param string $message The message to print out.
* @param string $type The type of notification. See constants on \core\output\notification.
* @param ?string $type The type of notification. See constants on \core\output\notification.
* @param bool $closebutton Whether to show a close icon to remove the notification (default true).
* @return string the HTML to output.
*/
public function notification($message, $type = null) {
public function notification($message, $type = null, $closebutton = true) {
$typemappings = [
// Valid types.
'success' => \core\output\notification::NOTIFY_SUCCESS,
@ -2922,7 +2923,7 @@ EOD;
}
}
$notification = new \core\output\notification($message, $type);
$notification = new \core\output\notification($message, $type, $closebutton);
if (count($extraclasses)) {
$notification->set_extra_classes($extraclasses);
}
@ -4886,9 +4887,10 @@ class core_renderer_cli extends core_renderer {
*
* @param string $message The message to print out.
* @param string $type The type of notification. See constants on \core\output\notification.
* @param bool $closebutton Whether to show a close icon to remove the notification (default true).
* @return string A template fragment for a notification
*/
public function notification($message, $type = null) {
public function notification($message, $type = null, $closebutton = true) {
$message = clean_text($message);
if ($type === 'notifysuccess' || $type === 'success') {
return "++ $message ++\n";
@ -4972,8 +4974,10 @@ class core_renderer_ajax extends core_renderer {
*
* @param string $message The message to print out.
* @param string $type The type of notification. See constants on \core\output\notification.
* @param bool $closebutton Whether to show a close icon to remove the notification (default true).
*/
public function notification($message, $type = null) {}
public function notification($message, $type = null, $closebutton = true) {
}
/**
* Used to display a redirection message.

View File

@ -24,162 +24,173 @@
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
$capabilities = [
// Ability to see that the quiz exists, and the basic information
// about it, for example the start date and time limit.
'mod/quiz:view' => array(
'mod/quiz:view' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'guest' => CAP_ALLOW,
'student' => CAP_ALLOW,
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Ability to add a new quiz to the course.
'mod/quiz:addinstance' => array(
'mod/quiz:addinstance' => [
'riskbitmask' => RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
],
'clonepermissionsfrom' => 'moodle/course:manageactivities'
),
],
// Ability to do the quiz as a 'student'.
'mod/quiz:attempt' => array(
'mod/quiz:attempt' => [
'riskbitmask' => RISK_SPAM,
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'student' => CAP_ALLOW
)
),
]
],
// Ability for a 'Student' to review their previous attempts. Review by
// 'Teachers' is controlled by mod/quiz:viewreports.
'mod/quiz:reviewmyattempts' => array(
'mod/quiz:reviewmyattempts' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'student' => CAP_ALLOW
),
],
'clonepermissionsfrom' => 'moodle/quiz:attempt'
),
],
// Edit the quiz settings, add and remove questions.
'mod/quiz:manage' => array(
'mod/quiz:manage' => [
'riskbitmask' => RISK_SPAM,
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Edit the quiz overrides.
'mod/quiz:manageoverrides' => array(
'mod/quiz:manageoverrides' => [
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Preview the quiz.
'mod/quiz:preview' => array(
'captype' => 'write', // Only just a write.
// View the quiz overrides (only checked for users who don't have mod/quiz:manageoverrides.
'mod/quiz:viewoverrides' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Preview the quiz.
'mod/quiz:preview' => [
'captype' => 'write', // Only just a write.
'contextlevel' => CONTEXT_MODULE,
'archetypes' => [
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
]
],
// Manually grade and comment on student attempts at a question.
'mod/quiz:grade' => array(
'mod/quiz:grade' => [
'riskbitmask' => RISK_SPAM | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Regrade quizzes.
'mod/quiz:regrade' => array(
'mod/quiz:regrade' => [
'riskbitmask' => RISK_SPAM,
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
],
'clonepermissionsfrom' => 'mod/quiz:grade'
),
],
// View the quiz reports.
'mod/quiz:viewreports' => array(
'mod/quiz:viewreports' => [
'riskbitmask' => RISK_PERSONAL,
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Delete attempts using the overview report.
'mod/quiz:deleteattempts' => array(
'mod/quiz:deleteattempts' => [
'riskbitmask' => RISK_DATALOSS,
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
]
],
// Do not have the time limit imposed. Used for accessibility legislation compliance.
'mod/quiz:ignoretimelimits' => array(
'mod/quiz:ignoretimelimits' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array()
),
'archetypes' => []
],
// Receive a confirmation message of own quiz submission.
'mod/quiz:emailconfirmsubmission' => array(
'mod/quiz:emailconfirmsubmission' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array()
),
'archetypes' => []
],
// Receive a notification message of other peoples' quiz submissions.
'mod/quiz:emailnotifysubmission' => array(
'mod/quiz:emailnotifysubmission' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array()
),
'archetypes' => []
],
// Receive a notification message when a quiz attempt becomes overdue.
'mod/quiz:emailwarnoverdue' => array(
'mod/quiz:emailwarnoverdue' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array()
),
);
'archetypes' => []
],
];

View File

@ -1,3 +1,4 @@
numattemptsmade,mod_quiz
reviewofattempt,mod_quiz
reviewofpreview,mod_quiz
reviewofpreview,mod_quiz
settingsoverrides,mod_quiz

View File

@ -613,6 +613,9 @@ $string['overridedeleteusersure'] = 'Are you sure you want to delete the overrid
$string['overridegroup'] = 'Override group';
$string['overridegroupeventname'] = '{$a->quiz} - {$a->group}';
$string['overrides'] = 'Overrides';
$string['overridesforquiz'] = 'Settings overrides: {$a}';
$string['overridesnoneforgroups'] = 'No group settings overrides have been created for this quiz.';
$string['overridesnoneforusers'] = 'No user settings overrides have been created for this quiz.';
$string['overrideuser'] = 'Override user';
$string['overrideusereventname'] = '{$a->quiz} - Override';
$string['pageshort'] = 'P';
@ -724,7 +727,8 @@ $string['quizisopen'] = 'This quiz is open';
$string['quizisclosedwillopen'] = 'Quiz closed (opens {$a})';
$string['quizisopenwillclose'] = 'Quiz open (closes {$a})';
$string['quiz:manage'] = 'Manage quizzes';
$string['quiz:manageoverrides'] = 'Manage quiz overrides';
$string['quiz:manageoverrides'] = 'Manage quiz settings overrides';
$string['quiz:viewoverrides'] = 'View quiz settings overrides';
$string['quiznavigation'] = 'Quiz navigation';
$string['quizopen'] = 'Open the quiz';
$string['quizeventopens'] = '{$a} opens';
@ -886,7 +890,6 @@ $string['serveridentifier'] = 'Identifier';
$string['serverinfo'] = 'Server information';
$string['servers'] = 'Servers';
$string['serverurl'] = 'Server URL';
$string['settingsoverrides'] = 'Settings overrides';
$string['shortanswer'] = 'Short answer';
$string['show'] = 'Show';
$string['showall'] = 'Show all questions on one page';
@ -1008,3 +1011,4 @@ $string['yourfinalgradeis'] = 'Your final grade for this quiz is {$a}.';
$string['numattemptsmade'] = '{$a} attempts made on this quiz';
$string['reviewofattempt'] = 'Review of attempt {$a}';
$string['reviewofpreview'] = 'Review of preview';
$string['settingsoverrides'] = 'Settings overrides';

View File

@ -1716,7 +1716,7 @@ function quiz_extend_settings_navigation($settings, $quiznode) {
$beforekey = $keys[$i + 1];
}
if (has_capability('mod/quiz:manageoverrides', $PAGE->cm->context)) {
if (has_any_capability(['mod/quiz:manageoverrides', 'mod/quiz:viewoverrides'], $PAGE->cm->context)) {
$url = new moodle_url('/mod/quiz/overrides.php', array('cmid'=>$PAGE->cm->id));
$node = navigation_node::create(get_string('groupoverrides', 'quiz'),
new moodle_url($url, array('mode'=>'group')),

View File

@ -22,7 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../config.php');
require_once($CFG->dirroot.'/mod/quiz/lib.php');
require_once($CFG->dirroot.'/mod/quiz/locallib.php');
@ -33,14 +32,17 @@ $cmid = required_param('cmid', PARAM_INT);
$mode = optional_param('mode', '', PARAM_ALPHA); // One of 'user' or 'group', default is 'group'.
list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'quiz');
$quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST);
$quiz = $DB->get_record('quiz', ['id' => $cm->instance], '*', MUST_EXIST);
require_login($course, false, $cm);
$context = context_module::instance($cm->id);
// Check the user has the required capabilities to list overrides.
require_capability('mod/quiz:manageoverrides', $context);
$canedit = has_capability('mod/quiz:manageoverrides', $context);
if (!$canedit) {
require_capability('mod/quiz:viewoverrides', $context);
}
$quizgroupmode = groups_get_activity_groupmode($cm);
$accessallgroups = ($quizgroupmode == NOGROUPS) || has_capability('moodle/site:accessallgroups', $context);
@ -58,16 +60,14 @@ if ($mode != "user" and $mode != "group") {
}
$groupmode = ($mode == "group");
$url = new moodle_url('/mod/quiz/overrides.php', array('cmid'=>$cm->id, 'mode'=>$mode));
$url = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id, 'mode' => $mode]);
$title = get_string('overridesforquiz', 'quiz',
format_string($quiz->name, true, ['context' => $context]));
$PAGE->set_url($url);
// Display a list of overrides.
$PAGE->set_pagelayout('admin');
$PAGE->set_title(get_string('overrides', 'quiz'));
$PAGE->set_title($title);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context)));
// Delete orphaned group overrides.
$sql = 'SELECT o.id
@ -76,7 +76,7 @@ $sql = 'SELECT o.id
WHERE o.groupid IS NOT NULL
AND g.id IS NULL
AND o.quiz = ?';
$params = array($quiz->id);
$params = [$quiz->id];
$orphaned = $DB->get_records_sql($sql, $params);
if (!empty($orphaned)) {
$DB->delete_records_list('quiz_overrides', 'id', array_keys($orphaned));
@ -131,16 +131,18 @@ if ($groupmode) {
// Initialise table.
$table = new html_table();
$table->headspan = array(1, 2, 1);
$table->colclasses = array('colname', 'colsetting', 'colvalue', 'colaction');
$table->head = array(
$colname,
get_string('overrides', 'quiz'),
get_string('action'),
);
$table->headspan = [1, 2, 1];
$table->colclasses = ['colname', 'colsetting', 'colvalue', 'colaction'];
$table->head = [
$colname,
get_string('overrides', 'quiz'),
];
if ($canedit) {
$table->head[] = get_string('action');
}
$userurl = new moodle_url('/user/view.php', array());
$groupurl = new moodle_url('/group/overview.php', array('id' => $cm->course));
$userurl = new moodle_url('/user/view.php', []);
$groupurl = new moodle_url('/group/overview.php', ['id' => $cm->course]);
$overridedeleteurl = new moodle_url('/mod/quiz/overridedelete.php');
$overrideediturl = new moodle_url('/mod/quiz/overrideedit.php');
@ -149,11 +151,8 @@ $hasinactive = false; // Whether there are any inactive overrides.
foreach ($overrides as $override) {
$fields = array();
$values = array();
// Check if this override is active.
$active = true;
// Check for inactive overrides.
if (!$groupmode) {
if (!has_capability('mod/quiz:attempt', $context, $override->userid)) {
// User not allowed to take the quiz.
@ -163,6 +162,13 @@ foreach ($overrides as $override) {
$active = false;
}
}
if (!$active) {
$hasinactive = true;
}
// Prepare the information about which settings are overridden.
$fields = [];
$values = [];
// Format timeopen.
if (isset($override->timeopen)) {
@ -170,28 +176,24 @@ foreach ($overrides as $override) {
$values[] = $override->timeopen > 0 ?
userdate($override->timeopen) : get_string('noopen', 'quiz');
}
// Format timeclose.
if (isset($override->timeclose)) {
$fields[] = get_string('quizcloses', 'quiz');
$values[] = $override->timeclose > 0 ?
userdate($override->timeclose) : get_string('noclose', 'quiz');
}
// Format timelimit.
if (isset($override->timelimit)) {
$fields[] = get_string('timelimit', 'quiz');
$values[] = $override->timelimit > 0 ?
format_time($override->timelimit) : get_string('none', 'quiz');
}
// Format number of attempts.
if (isset($override->attempts)) {
$fields[] = get_string('attempts', 'quiz');
$values[] = $override->attempts > 0 ?
$override->attempts : get_string('unlimited');
}
// Format password.
if (isset($override->password)) {
$fields[] = get_string('requirepassword', 'quiz');
@ -199,110 +201,130 @@ foreach ($overrides as $override) {
get_string('enabled', 'quiz') : get_string('none', 'quiz');
}
// Icons.
$iconstr = '';
// Edit.
$editurlstr = $overrideediturl->out(true, array('id' => $override->id));
$iconstr = '<a title="' . get_string('edit') . '" href="'. $editurlstr . '">' .
$OUTPUT->pix_icon('t/edit', get_string('edit')) . '</a> ';
// Duplicate.
$copyurlstr = $overrideediturl->out(true,
array('id' => $override->id, 'action' => 'duplicate'));
$iconstr .= '<a title="' . get_string('copy') . '" href="' . $copyurlstr . '">' .
$OUTPUT->pix_icon('t/copy', get_string('copy')) . '</a> ';
// Delete.
$deleteurlstr = $overridedeleteurl->out(true,
array('id' => $override->id, 'sesskey' => sesskey()));
$iconstr .= '<a title="' . get_string('delete') . '" href="' . $deleteurlstr . '">' .
$OUTPUT->pix_icon('t/delete', get_string('delete')) . '</a> ';
// Prepare the information about who this override applies to.
if ($groupmode) {
$usergroupstr = '<a href="' . $groupurl->out(true,
array('group' => $override->groupid)) . '" >' . $override->name . '</a>';
['group' => $override->groupid]) . '" >' . $override->name . '</a>';
} else {
$usergroupstr = '<a href="' . $userurl->out(true,
array('id' => $override->userid)) . '" >' . fullname($override) . '</a>';
['id' => $override->userid]) . '" >' . fullname($override) . '</a>';
}
$class = '';
if (!$active) {
$class = "dimmed_text";
$usergroupstr .= '*';
$hasinactive = true;
}
$usergroupcell = new html_table_cell();
$usergroupcell->rowspan = count($fields);
$usergroupcell->text = $usergroupstr;
$actioncell = new html_table_cell();
$actioncell->rowspan = count($fields);
$actioncell->text = $iconstr;
// Prepare the actions.
if ($canedit) {
// Icons.
$iconstr = '';
// Edit.
$editurlstr = $overrideediturl->out(true, ['id' => $override->id]);
$iconstr = '<a title="' . get_string('edit') . '" href="' . $editurlstr . '">' .
$OUTPUT->pix_icon('t/edit', get_string('edit')) . '</a> ';
// Duplicate.
$copyurlstr = $overrideediturl->out(true,
['id' => $override->id, 'action' => 'duplicate']);
$iconstr .= '<a title="' . get_string('copy') . '" href="' . $copyurlstr . '">' .
$OUTPUT->pix_icon('t/copy', get_string('copy')) . '</a> ';
// Delete.
$deleteurlstr = $overridedeleteurl->out(true,
['id' => $override->id, 'sesskey' => sesskey()]);
$iconstr .= '<a title="' . get_string('delete') . '" href="' . $deleteurlstr . '">' .
$OUTPUT->pix_icon('t/delete', get_string('delete')) . '</a> ';
$actioncell = new html_table_cell();
$actioncell->rowspan = count($fields);
$actioncell->text = $iconstr;
}
// Add the data to the table.
for ($i = 0; $i < count($fields); ++$i) {
$row = new html_table_row();
$row->attributes['class'] = $class;
if (!$active) {
$row->attributes['class'] = 'dimmed_text';
}
if ($i == 0) {
$row->cells[] = $usergroupcell;
}
$cell1 = new html_table_cell();
$cell1->text = $fields[$i];
$row->cells[] = $cell1;
$cell2 = new html_table_cell();
$cell2->text = $values[$i];
$row->cells[] = $cell2;
if ($i == 0) {
$labelcell = new html_table_cell();
$labelcell->text = $fields[$i];
$row->cells[] = $labelcell;
$valuecell = new html_table_cell();
$valuecell->text = $values[$i];
$row->cells[] = $valuecell;
if ($canedit && $i == 0) {
$row->cells[] = $actioncell;
}
$table->data[] = $row;
}
}
// Display a list of overrides.
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
// Output the table and button.
echo html_writer::start_tag('div', array('id' => 'quizoverrides'));
echo html_writer::start_tag('div', ['id' => 'quizoverrides']);
if (count($table->data)) {
echo html_writer::table($table);
} else {
if ($groupmode) {
echo $OUTPUT->notification(get_string('overridesnoneforgroups', 'quiz'), 'info', false);
} else {
echo $OUTPUT->notification(get_string('overridesnoneforusers', 'quiz'), 'info', false);
}
}
if ($hasinactive) {
echo $OUTPUT->notification(get_string('inactiveoverridehelp', 'quiz'), 'dimmed_text');
echo $OUTPUT->notification(get_string('inactiveoverridehelp', 'quiz'), 'info', false);
}
echo html_writer::start_tag('div', array('class' => 'buttons'));
$options = array();
if ($groupmode) {
if (empty($groups)) {
// There are no groups.
echo $OUTPUT->notification(get_string('groupsnone', 'quiz'), 'error');
$options['disabled'] = true;
}
echo $OUTPUT->single_button($overrideediturl->out(true,
array('action' => 'addgroup', 'cmid' => $cm->id)),
get_string('addnewgroupoverride', 'quiz'), 'post', $options);
} else {
$users = array();
// See if there are any students in the quiz.
if ($accessallgroups) {
$users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id');
$nousermessage = get_string('usersnone', 'quiz');
} else if ($groups) {
$users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id', '', '', '', array_keys($groups));
$nousermessage = get_string('usersnone', 'quiz');
if ($canedit) {
echo html_writer::start_tag('div', ['class' => 'buttons']);
$options = [];
if ($groupmode) {
if (empty($groups)) {
// There are no groups.
echo $OUTPUT->notification(get_string('groupsnone', 'quiz'), 'error');
$options['disabled'] = true;
}
echo $OUTPUT->single_button($overrideediturl->out(true,
['action' => 'addgroup', 'cmid' => $cm->id]),
get_string('addnewgroupoverride', 'quiz'), 'post', $options);
} else {
$nousermessage = get_string('groupsnone', 'quiz');
}
$info = new \core_availability\info_module($cm);
$users = $info->filter_user_list($users);
$users = [];
// See if there are any students in the quiz.
if ($accessallgroups) {
$users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id');
$nousermessage = get_string('usersnone', 'quiz');
} else if ($groups) {
$users = get_users_by_capability($context, 'mod/quiz:attempt', 'u.id', '', '', '', array_keys($groups));
$nousermessage = get_string('usersnone', 'quiz');
} else {
$nousermessage = get_string('groupsnone', 'quiz');
}
$info = new \core_availability\info_module($cm);
$users = $info->filter_user_list($users);
if (empty($users)) {
// There are no students.
echo $OUTPUT->notification($nousermessage, 'error');
$options['disabled'] = true;
if (empty($users)) {
// There are no students.
echo $OUTPUT->notification($nousermessage, 'error');
$options['disabled'] = true;
}
echo $OUTPUT->single_button($overrideediturl->out(true,
['action' => 'adduser', 'cmid' => $cm->id]),
get_string('addnewuseroverride', 'quiz'), 'get', $options);
}
echo $OUTPUT->single_button($overrideediturl->out(true,
array('action' => 'adduser', 'cmid' => $cm->id)),
get_string('addnewuseroverride', 'quiz'), 'get', $options);
echo html_writer::end_tag('div');
}
echo html_writer::end_tag('div');
echo html_writer::end_tag('div');
// Finish the page.

View File

@ -2,7 +2,7 @@
Feature: Quiz group override
In order to grant a group special access to a quiz
As a teacher
I need to create an override for thta group.
I need to create an override for that group.
Background:
Given the following "users" exist:
@ -13,6 +13,7 @@ Feature: Quiz group override
| student2 | Sam 2 | Student 2 | student2@example.com |
| teacher3 | Terry 3 | Teacher 3 | teacher3@example.com |
| student3 | Sam 3 | Student 3 | student3@example.com |
| helper | Exam | Helper | helper@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
@ -24,6 +25,7 @@ Feature: Quiz group override
| student2 | C1 | student |
| teacher3 | C1 | editingteacher |
| student3 | C1 | student |
| helper | C1 | teacher |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
@ -38,6 +40,9 @@ Feature: Quiz group override
| teacher2 | G2 |
| teacher2 | G3 |
| student3 | G3 |
| helper | G1 |
| helper | G2 |
| helper | G3 |
And the following "activities" exist:
| activity | name | intro | course | idnumber | groupmode |
| quiz | Test quiz | Test quiz description | C1 | quiz1 | 1 |
@ -59,37 +64,49 @@ Feature: Quiz group override
Then I should see "No groups you can access."
And the "Add group override" "button" should be disabled
Scenario: A teacher with accessallgroups permission should see all group overrides
When I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "admin"
Scenario: A teacher can create an override
When I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "teacher1"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Attempts allowed | 2 |
| Override group | Group 1 |
| Attempts allowed | 2 |
And I press "Save and enter another override"
And I set the following fields to these values:
| Override group | Group 2 |
| Override group | Group 3 |
| Attempts allowed | 2 |
And I press "Save"
And I log out
And I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "teacher1"
Then I should see "Group 1" in the ".generaltable" "css_element"
And I should see "Group 2" in the ".generaltable" "css_element"
Then "Group 1" "table_row" should exist
Scenario: A teacher with accessallgroups permission should see all group overrides
Given the following "mod_quiz > group overrides" exist:
| quiz | group | attempts |
| Test quiz | G1 | 2 |
| Test quiz | G2 | 2 |
When I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "teacher1"
Then "Group 1" "table_row" should exist
And "Group 2" "table_row" should exist
Scenario: A teacher without accessallgroups permission should only see the group overrides within his/her groups, when the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
When I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "admin"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Attempts allowed | 2 |
And I press "Save and enter another override"
And I set the following fields to these values:
| Override group | Group 2 |
| Attempts allowed | 2 |
And I press "Save"
And I log out
And the following "mod_quiz > group overrides" exist:
| quiz | group | attempts |
| Test quiz | G1 | 2 |
| Test quiz | G2 | 2 |
When I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "teacher1"
Then I should see "Group 1" in the ".generaltable" "css_element"
And I should not see "Group 2" in the ".generaltable" "css_element"
Then "Group 1" "table_row" should exist
And "Group 2" "table_row" should not exist
Scenario: A non-editing teacher can see the overrides, but not change them
Given the following "mod_quiz > group overrides" exist:
| quiz | group | attempts |
| Test quiz | G1 | 2 |
| Test quiz | G2 | 2 |
When I am on the "Test quiz" "mod_quiz > Group overrides" page logged in as "helper"
Then "Group 1" "table_row" should exist
And "Group 2" "table_row" should exist
And "Add group override" "button" should not exist
And "Edit" "link" should not exist in the "Group 1" "table_row"
And "Copy" "link" should not exist in the "Group 1" "table_row"
And "Delete" "link" should not exist in the "Group 1" "table_row"

View File

@ -7,7 +7,8 @@ Feature: Quiz user override
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | One | teacher1@example.com |
| teacher | Teacher | One | teacher@example.com |
| helper | Exam | Helper | helper@example.com |
| student1 | Student | One | student1@example.com |
| student2 | Student | Two | student2@example.com |
And the following "courses" exist:
@ -15,18 +16,17 @@ Feature: Quiz user override
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| teacher | C1 | editingteacher |
| helper | C1 | teacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activities" exist:
| activity | name | intro | course | idnumber |
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
@javascript
Scenario: Add, modify then delete a user override
Given I log in as "teacher1"
And I am on "Course 1" course homepage
When I follow "Quiz 1"
Given the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Test quiz | C1 | quiz1 |
And I am on the "Test quiz" "mod_quiz > View" page logged in as "teacher"
And I navigate to "User overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
@ -38,26 +38,24 @@ Feature: Quiz user override
| timeclose[hour] | 08 |
| timeclose[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
Then I click on "Edit" "link" in the "Student One" "table_row"
Then I should see "Wednesday, 1 January 2020, 8:00"
And I click on "Edit" "link" in the "Student One" "table_row"
And I set the following fields to these values:
| timeclose[year] | 2030 |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I click on "Delete" "link"
And I press "Continue"
And I should not see "Student One"
@javascript
Scenario: Being able to modify a user override when the quiz is not available to the student
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Quiz 1"
And I navigate to "Edit settings" in current page administration
And I expand all fieldsets
And I set the field "Availability" to "Hide from students"
And I click on "Save and display" "button"
When I navigate to "User overrides" in current page administration
Scenario: Can add a user override when the quiz is not available to the student
Given the following "activities" exist:
| activity | name | course | idnumber | visible |
| quiz | Test quiz | C1 | quiz1 | 0 |
When I am on the "Test quiz" "mod_quiz > User overrides" page logged in as "teacher"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
@ -77,18 +75,15 @@ Feature: Quiz user override
And the following "group members" exist:
| user | group |
| student1 | G1 |
| teacher1 | G1 |
| teacher | G1 |
| student2 | G2 |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | idnumber | groupmode |
| quiz | Quiz 2 | Quiz 2 description | C1 | quiz2 | 1 |
When I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Quiz 2"
And I navigate to "User overrides" in current page administration
| activity | name | course | idnumber | groupmode |
| quiz | Test quiz | C1 | quiz1 | 1 |
When I am on the "Test quiz" "mod_quiz > User overrides" page logged in as "teacher"
And I press "Add user override"
Then the "Override user" select box should contain "Student One, student1@example.com"
And the "Override user" select box should not contain "Student Two, student2@example.com"
@ -104,11 +99,25 @@ Feature: Quiz user override
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | idnumber | groupmode |
| quiz | Quiz 2 | Quiz 2 description | C1 | quiz2 | 1 |
When I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Quiz 2"
And I navigate to "User overrides" in current page administration
| activity | name | course | idnumber | groupmode |
| quiz | Test quiz | C1 | quiz1 | 1 |
When I am on the "Test quiz" "mod_quiz > User overrides" page logged in as "teacher"
Then I should see "No groups you can access."
And the "Add user override" "button" should be disabled
Scenario: A non-editing teacher can see the overrides, but not change them
Given the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Test quiz | C1 | quiz1 |
And the following "mod_quiz > user overrides" exist:
| quiz | user | attempts |
| Test quiz | student1 | 2 |
| Test quiz | student2 | 2 |
And I am on the "Test quiz" "mod_quiz > View" page logged in as "helper"
When I navigate to "User overrides" in current page administration
Then "Student One" "table_row" should exist
And "Student Two" "table_row" should exist
And "Add user override" "button" should not exist
And "Edit" "link" should not exist in the "Student One" "table_row"
And "Copy" "link" should not exist in the "Student One" "table_row"
And "Delete" "link" should not exist in the "Student One" "table_row"

View File

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2021052500;
$plugin->version = 2021052501;
$plugin->requires = 2021052500;
$plugin->component = 'mod_quiz';