MDL-76665 quizaccess_seb: Allow disable of SEB templates when in use.

This commit is contained in:
Michael Kotlyar
2024-09-04 10:23:53 +01:00
parent 13c12756b4
commit 14228164bc
6 changed files with 170 additions and 14 deletions
@@ -25,6 +25,8 @@
*/
use quizaccess_seb\seb_quiz_settings;
use quizaccess_seb\settings_provider;
use quizaccess_seb\template;
defined('MOODLE_INTERNAL') || die();
@@ -73,7 +75,15 @@ class restore_quizaccess_seb_subplugin extends restore_mod_quiz_access_subplugin
unset($data->id);
$data->timecreated = $data->timemodified = time();
$data->usermodified = $USER->id;
$DB->insert_record(quizaccess_seb\seb_quiz_settings::TABLE, $data);
// Do not use template if it is no longer enabled.
if ($data->requiresafeexambrowser == settings_provider::USE_SEB_TEMPLATE &&
!$DB->record_exists(template::TABLE, ['id' => $data->templateid, 'enabled' => '1'])) {
$data->templateid = 0;
$data->requiresafeexambrowser = settings_provider::USE_SEB_NO;
}
$DB->insert_record(seb_quiz_settings::TABLE, $data);
// Process attached files.
$this->add_related_files('quizaccess_seb', 'filemanager_sebconfigfile', null);
@@ -112,7 +122,10 @@ class restore_quizaccess_seb_subplugin extends restore_mod_quiz_access_subplugin
}
// Update the restored quiz settings to use restored template.
$DB->set_field(\quizaccess_seb\seb_quiz_settings::TABLE, 'templateid', $template->get('id'), ['quizid' => $quizid]);
// Check if template is enabled before using it.
if ($template->get('enabled')) {
$DB->set_field(seb_quiz_settings::TABLE, 'templateid', $template->get('id'), ['quizid' => $quizid]);
}
}
}
@@ -62,12 +62,11 @@ class template extends \core\form\persistent {
$mform->addElement('selectyesno', 'enabled', get_string('enabled', 'quizaccess_seb'));
$mform->setType('enabled', PARAM_INT);
$this->add_action_buttons();
if (!empty($this->get_persistent()) && !$this->get_persistent()->can_delete()) {
$mform->hardFreezeAllVisibleExcept([]);
$mform->addElement('cancel');
if ($this->get_persistent()->get('id')) {
$mform->hardFreezeAllVisibleExcept(['enabled']);
}
$this->add_action_buttons();
}
/**
@@ -212,12 +212,13 @@ class settings_provider {
* @param \MoodleQuickForm $mform the wrapped MoodleQuickForm.
*/
protected static function add_seb_templates(\mod_quiz_mod_form $quizform, \MoodleQuickForm $mform) {
if (self::can_use_seb_template($quizform->get_context()) || self::is_conflicting_permissions($quizform->get_context())) {
$context = $quizform->get_context();
if (self::can_use_seb_template($context) || self::is_conflicting_permissions($context)) {
$element = $mform->createElement(
'select',
'seb_templateid',
get_string('seb_templateid', 'quizaccess_seb'),
self::get_template_options()
self::get_template_options($context->instanceid)
);
} else {
$element = $mform->createElement('hidden', 'seb_templateid');
@@ -230,7 +231,7 @@ class settings_provider {
// In case if the user can't use templates, but the quiz is configured to use them,
// we'd like to display template, but freeze it.
if (self::is_conflicting_permissions($quizform->get_context())) {
if (self::is_conflicting_permissions($context)) {
self::freeze_element($quizform, $mform, 'seb_templateid');
}
}
@@ -566,7 +567,7 @@ class settings_provider {
}
if (self::can_use_seb_template($context) || self::is_conflicting_permissions($context)) {
if (!empty(self::get_template_options())) {
if (!empty(self::get_template_options($context->instanceid))) {
$options[self::USE_SEB_TEMPLATE] = get_string('seb_use_template', 'quizaccess_seb');
}
}
@@ -584,10 +585,18 @@ class settings_provider {
* Returns a list of templates.
* @return array
*/
protected static function get_template_options(): array {
protected static function get_template_options($cmid): array {
$templates = [];
$records = template::get_records(['enabled' => 1], 'name');
if ($records) {
$templatetable = template::TABLE;
$sebquizsettingstable = seb_quiz_settings::TABLE;
$select = "enabled = 1
OR EXISTS (
SELECT 1
FROM {{$sebquizsettingstable}}
WHERE templateid = {{$templatetable}}.id
AND cmid = ?
)";
if ($records = template::get_records_select($select, [$cmid], 'id, name')) {
foreach ($records as $record) {
$templates[$record->get('id')] = $record->get('name');
}
@@ -193,6 +193,48 @@ class backup_restore_test extends \advanced_testcase {
$this->validate_backup_restore($newcm);
}
/**
* Test backup and restore when using template when said template is disabled.
*
* @covers \quizaccess_seb\seb_quiz_settings::get_record
* @covers \restore_quizaccess_seb_subplugin::process_quizaccess_seb_quizsettings
*/
public function test_backup_restore_disabled_template_config(): void {
$this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
$expected = seb_quiz_settings::get_record(['quizid' => $this->quiz->id]);
$template = $this->create_template();
$expected->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE);
$expected->set('templateid', $template->get('id'));
$expected->save();
// Disable template.
$template->set('enabled', 0);
$template->save();
$this->assertEquals(1, seb_quiz_settings::count_records());
$newcm = $this->backup_and_restore_quiz();
$this->assertEquals(2, seb_quiz_settings::count_records());
$actual = seb_quiz_settings::get_record(['quizid' => $newcm->instance]);
// Test that the restored quiz no longer uses SEB.
$expected = seb_quiz_settings::get_record(['quizid' => $this->quiz->id]);
$this->assertEquals(0, $actual->get('templateid'));
$this->assertEquals(settings_provider::USE_SEB_NO, $actual->get('requiresafeexambrowser'));
$this->assertEquals($expected->get('showsebdownloadlink'), $actual->get('showsebdownloadlink'));
$this->assertEquals($expected->get('allowuserquitseb'), $actual->get('allowuserquitseb'));
$this->assertEquals($expected->get('quitpassword'), $actual->get('quitpassword'));
$this->assertEquals($expected->get('allowedbrowserexamkeys'), $actual->get('allowedbrowserexamkeys'));
// Validate specific SEB config settings.
foreach (settings_provider::get_seb_config_elements() as $name => $notused) {
$name = preg_replace("/^seb_/", "", $name);
$this->assertEquals($expected->get($name), $actual->get($name));
}
}
/**
* Test backup and restore when using uploaded file.
*/
@@ -8,6 +8,7 @@ Feature: Safe Exam Browser settings in quiz edit form
And the following "activities" exist:
| activity | course | section | name |
| quiz | C1 | 1 | Quiz 1 |
| quiz | C1 | 1 | Quiz 2 |
Scenario: Quiz setting "Require the use of Safe Exam Browser" has all types, except "Use an existing template".
When I am on the "Quiz 1" "quiz activity editing" page logged in as admin
@@ -232,3 +233,34 @@ Feature: Safe Exam Browser settings in quiz edit form
Then I should not see "Allowed browser exam keys"
Then I should not see "Safe Exam Browser config template"
Then I should not see "Template 1"
Scenario: Disable templates that are already in use and seeing their visibility in settings
Given the following "quizaccess_seb > seb templates" exist:
| name | enabled |
| Template 1 | 1 |
| Template 2 | 0 |
# Set Quiz 1 template to Template 1
When I am on the "Quiz 1" "quiz activity editing" page logged in as admin
And I expand all fieldsets
And I set the field "Require the use of Safe Exam Browser" to "Yes Use an existing template"
Then I should see "Safe Exam Browser config template"
And the "Safe Exam Browser config template" select box should contain "Template 1"
And the "Safe Exam Browser config template" select box should not contain "Template 2"
And I set the field "Safe Exam Browser config template" to "Template 1"
And I press "Save and return to course"
# Disable Template 1
And I navigate to "Plugins > Activity modules > Category: Quiz > Safe Exam Browser templates" in site administration
And I click on "Edit" "link" in the "Template 1" "table_row"
And I set the field "Enabled" to "No"
And I press "Save changes"
# Check Quiz 1 is still using Template 1
When I am on the "Quiz 1" "quiz activity editing" page logged in as admin
And I expand all fieldsets
And the field "Require the use of Safe Exam Browser" matches value "Yes Use an existing template"
Then I should see "Template 1"
And the "Safe Exam Browser config template" select box should contain "Template 1"
And the "Safe Exam Browser config template" select box should not contain "Template 2"
# Check Quiz 3 cannot use any templates as they're all disabled
When I am on the "Quiz 2" "quiz activity editing" page logged in as admin
And I expand all fieldsets
And the "Require the use of Safe Exam Browser" select box should not contain "Yes Use an existing template"
@@ -16,6 +16,10 @@
namespace quizaccess_seb;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/test_helper_trait.php');
/**
* PHPUnit tests for template class.
*
@@ -25,6 +29,7 @@ namespace quizaccess_seb;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class template_test extends \advanced_testcase {
use \quizaccess_seb_test_helper_trait;
/**
* Called before every test.
@@ -140,4 +145,60 @@ class template_test extends \advanced_testcase {
$this->assertFalse($template->can_delete());
}
/**
* Test that a disabled template no longer shows up in quiz SEB settings other than quizzes already using it.
*
* @covers \quizaccess_seb\seb_quiz_settings::get_record
* @covers \quizaccess_seb\settings_provider::get_requiresafeexambrowser_options
*/
public function test_disabled_template_quiz_setting_options(): void {
// Create quiz and fetch standard SEB requirement options.
$this->setAdminUser();
$this->course = $this->getDataGenerator()->create_course();
$templateoptionstr = get_string('seb_use_template', 'quizaccess_seb');
// Create a quiz.
$this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
$context = \context_module::instance($this->quiz->cmid);
// Check there is no template option (as there aren't any).
$options = settings_provider::get_requiresafeexambrowser_options($context);
$this->assertNotContainsEquals($templateoptionstr, $options);
// Create a template.
$data = new \stdClass();
$data->name = 'Test name';
$data->description = 'Test description';
$data->enabled = 1;
$data->content = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb');
$template = new template(0, $data);
$template->save();
// Check options now include template option.
$options = settings_provider::get_requiresafeexambrowser_options($context);
$this->assertContainsEquals($templateoptionstr, $options);
// Set SEB setting to use template for quiz.
$settings = seb_quiz_settings::get_record(['quizid' => $this->quiz->id]);
$settings->set('templateid', $template->get('id'));
$settings->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE);
$settings->save();
// Disable template.
$template->set('enabled', 0);
$template->save();
// Check option still exists on current quiz.
$options = settings_provider::get_requiresafeexambrowser_options($context);
$this->assertContainsEquals($templateoptionstr, $options);
// Create a new quiz.
$newquiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
$context = \context_module::instance($newquiz->cmid);
// Check there is no template option (as the template is now disabled).
$options = settings_provider::get_requiresafeexambrowser_options($context);
$this->assertNotContainsEquals($templateoptionstr, $options);
}
}