Skip to content

Commit

Permalink
MDL-80945 quiz: Add hooks to override access settings.
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Kotlyar committed Dec 2, 2024
1 parent a8b2acd commit 2a6da3b
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 22 deletions.
144 changes: 144 additions & 0 deletions mod/quiz/classes/access_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace mod_quiz;

use core_component;
use mod_quiz\form\edit_override_form;
use mod_quiz\form\preflight_check_form;
use mod_quiz\local\access_rule_base;
use mod_quiz\output\renderer;
Expand Down Expand Up @@ -279,6 +280,149 @@ public static function load_quiz_and_settings(int $quizid): stdClass {
return $quiz;
}

/**
* Add any form fields that the access rules require to the override form.
*
* Note that the standard plugins do not use this mechanism, becuase all their
* settings are stored in the quiz table.
*
* @param edit_override_form $quizform the quiz override settings form being built.
* @param MoodleQuickForm $mform the wrapped MoodleQuickForm.
* @return boolean return true if fields have been added.
*/
public static function add_override_form_fields(
edit_override_form $quizform, MoodleQuickForm $mform): bool {
$fieldsadded = false;
foreach (self::get_rule_classes() as $rule) {
if ($element = $rule::get_override_form_section_header()) {
$mform->addElement('header', $element['name'], $element['title']);
$mform->setExpanded($element['name'], $rule::get_override_form_section_expand($quizform));
$rule::add_override_form_fields($quizform, $mform);
$fieldsadded = true;
}
}
return $fieldsadded;
}

/**
* Validate the data from any form fields added using {@see add_override_form_fields()}.
*
* @param array $errors the errors found so far.
* @param array $data the submitted form data.
* @param array $files information about any uploaded files.
* @param edit_override_form $quizform the quiz override form object.
* @return array $errors the updated $errors array.
*/
public static function validate_override_form_fields(array $errors,
array $data, array $files, edit_override_form $quizform): array {

foreach (self::get_rule_classes() as $rule) {
$errors = $rule::validate_override_form_fields($errors, $data, $files, $quizform);
}

return $errors;
}

/**
* Save any submitted settings when the quiz override settings form is submitted.
*
* @param array $override data from the override form.
* @return void
*/
public static function save_override_settings(array $override): void {

foreach (self::get_rule_classes() as $rule) {
$rule::save_override_settings($override);
}
}

/**
* Delete any rule-specific override settings when the quiz override is deleted.
*
* @param int $quizid all overrides being deleted should belong to the same quiz.
* @param array $overrides an array of override objects to be deleted.
* @return void
*/
public static function delete_override_settings($quizid, $overrides): void {
foreach (self::get_rule_classes() as $rule) {
$rule::delete_override_settings($quizid, $overrides);
}
}

/**
* Get components of the SQL query to fetch the access rule components' override
* settings. To be used as part of a quiz_override query to reference.
*
* @param string $overridetablename Name of the table to reference for joins.
* @return array 'selects', 'joins' and 'params'.
*/
public static function get_override_settings_sql($overridetablename = 'quiz_overrides'): array {
$allfields = '';
$alljoins = '';
$allparams = [];

foreach (self::get_rule_classes() as $rule) {
[$fields, $joins, $params] = $rule::get_override_settings_sql($overridetablename);

if ($fields) {
if ($allfields) {
$allfields .= ', ';
}
$allfields .= $fields;
}
if ($joins) {
$alljoins .= ' ' . $joins;
}
if ($params) {
$allparams += $params;
}
}

return [$allfields, $alljoins, $allparams];
}

/**
* Retrieve all keys of fields to be used in the override form.
*
* @return array
*/
public static function get_override_setting_keys(): array {
$keys = [];
foreach (self::get_rule_classes() as $rule) {
$keys += $rule::get_override_setting_keys();
}
return $keys;
}

/**
* Retrieve keys of fields that are required to be filled in.
*
* @return array
*/
public static function get_override_required_setting_keys(): array {
$keys = [];
foreach (self::get_rule_classes() as $rule) {
$keys += $rule::get_override_required_setting_keys();
}
return $keys;
}

/**
* Update fields and values of the override table using the override settings.
*
* @param object $override the override data to use to update the $fields and $values.
* @param array $fields the fields to populate.
* @param array $values the fields to populate.
* @param context $context the context of which the override is being applied to.
* @return array
*/
public static function add_override_table_fields($override, $fields, $values, $context): array {
foreach (self::get_rule_classes() as $rule) {
[$fields, $values] = $rule::add_override_table_fields($override, $fields, $values, $context);
}
return [$fields, $values];
}

/**
* Get an array of the class names of all the active rules.
*
Expand Down
33 changes: 33 additions & 0 deletions mod/quiz/classes/form/edit_override_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use moodle_url;
use moodleform;
use stdClass;
use mod_quiz\access_manager;

defined('MOODLE_INTERNAL') || die();

Expand Down Expand Up @@ -84,6 +85,30 @@ public function __construct(moodle_url $submiturl,
parent::__construct($submiturl);
}

/**
* Return the course context for new modules, or the module context for existing modules.
* @return context_module
*/
public function get_context(): context_module {
return $this->context;
}

/**
* Get the quiz override ID.
* @return int
*/
public function get_overrideid(): int {
return $this->overrideid;
}

/**
* Get the quiz object.
* @return \stdClass
*/
public function get_quiz(): \stdClass {
return $this->quiz;
}

protected function definition() {
global $DB;

Expand Down Expand Up @@ -224,6 +249,11 @@ protected function definition() {
$mform->addHelpButton('attempts', 'attempts', 'quiz');
$mform->setDefault('attempts', $this->quiz->attempts);

// Access-rule fields.
if (access_manager::add_override_form_fields($this, $mform)) {
$mform->closeHeaderBefore('resetbutton');
}

// Submit buttons.
$mform->addElement('submit', 'resetbutton',
get_string('reverttodefaults', 'quiz'));
Expand Down Expand Up @@ -289,6 +319,9 @@ public function validation($data, $files): array {
}
}

// Apply access-rule validation.
$errors = access_manager::validate_override_form_fields($errors, $data, $files, $this);

return $errors;
}
}
114 changes: 114 additions & 0 deletions mod/quiz/classes/local/access_rule_base.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

namespace mod_quiz\local;

use mod_quiz\form\edit_override_form;
use mod_quiz\form\preflight_check_form;
use mod_quiz_mod_form;
use moodle_page;
Expand Down Expand Up @@ -353,4 +354,117 @@ public static function get_settings_sql($quizid) {
public static function get_extra_settings($quizid) {
return [];
}

/**
* Override form section header. If this is false, the plugin's override form fields will not appear.
*
* Array must have two keys. The 'name' key for the name of the heading element, and the 'title' key for the
* text to display in the heading.
*
* @return array|false (name, title)
*/
public static function get_override_form_section_header(): array|false {
return false;
}

/**
* Determine whether the rule section should be expanded or not in the override form.
*
* @param edit_override_form $quizform the quiz override settings form being built.
* @return bool set true if section should be expanded.
*/
public static function get_override_form_section_expand(edit_override_form $quizform): bool {
return false;
}

/**
* Add fields to the quiz override form.
*
* @param edit_override_form $quizform the quiz override settings form being built.
* @param MoodleQuickForm $mform the wrapped MoodleQuickForm.
* @return void
*/
public static function add_override_form_fields(
edit_override_form $quizform, MoodleQuickForm $mform): void {
// By default do nothing.
}

/**
* Validate the data from any form fields added using {@see add_override_form_fields()}.
*
* @param array $errors the errors found so far.
* @param array $data the submitted form data.
* @param array $files information about any uploaded files.
* @param edit_override_form $quizform the quiz override form object.
* @return array $errors the updated $errors array.
*/
public static function validate_override_form_fields(array $errors,
array $data, array $files, edit_override_form $quizform): array {
return $errors;
}

/**
* Save any submitted settings when the quiz override settings form is submitted.
*
* @param array $override data from the override form.
* @return void
*/
public static function save_override_settings($override): void {
// By default do nothing.
}

/**
* Delete any rule-specific override settings when the quiz override is deleted.
*
* @param int $quizid all overrides being deleted should belong to the same quiz.
* @param array $overrides an array of override objects to be deleted.
* @return void
*/
public static function delete_override_settings($quizid, $overrides): void {
// By default do nothing.
}

/**
* Provide form field keys in the override form as a string array
* e.g. ['rule_enabled', 'rule_password'].
*
* @return array
*/
public static function get_override_setting_keys(): array {
return [];
}

/**
* Provide required form field keys in the override form as a string array
* e.g. ['rule_enabled'].
*
* @return array
*/
public static function get_override_required_setting_keys(): array {
return [];
}

/**
* Get components of the SQL query to fetch the access rule components' override
* settings. To be used as part of a quiz_override query to reference.
*
* @param string $overridetablename Name of the table to reference for joins.
* @return array 'selects', 'joins' and 'params'.
*/
public static function get_override_settings_sql($overridetablename): array {
return ['', '', []];
}

/**
* Update fields and values of the override table using the override settings.
*
* @param object $override the override data to use to update the $fields and $values.
* @param array $fields the fields to populate.
* @param array $values the fields to populate.
* @param context $context the context of which the override is being applied to.
* @return array a pair of arrays. Fields and values, respectively.
*/
public static function add_override_table_fields($override, $fields, $values, $context): array {
return [$fields, $values];
}
}
Loading

0 comments on commit 2a6da3b

Please sign in to comment.