mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-71410 mod_quiz: Cache user and group overrides
This commit is contained in:
parent
660f7c08c5
commit
d61f18433f
110
mod/quiz/classes/cache/overrides.php
vendored
Normal file
110
mod/quiz/classes/cache/overrides.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Cache data source for the quiz overrides.
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2021 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mod_quiz\cache;
|
||||
|
||||
use cache_definition;
|
||||
|
||||
/**
|
||||
* Class quiz_overrides
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2021 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class overrides implements \cache_data_source {
|
||||
|
||||
/** @var overrides the singleton instance of this class. */
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Returns an instance of the data source class that the cache can use for loading data using the other methods
|
||||
* specified by this interface.
|
||||
*
|
||||
* @param cache_definition $definition
|
||||
* @return object
|
||||
*/
|
||||
public static function get_instance_for_cache(cache_definition $definition): overrides {
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new overrides();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the data for the key provided ready formatted for caching.
|
||||
*
|
||||
* @param string|int $key The key to load.
|
||||
* @return mixed What ever data should be returned, or false if it can't be loaded.
|
||||
* @throws \coding_exception
|
||||
*/
|
||||
public function load_for_cache($key) {
|
||||
global $DB;
|
||||
|
||||
[$quizid, $ug, $ugid] = explode('_', $key);
|
||||
$quizid = (int) $quizid;
|
||||
|
||||
switch ($ug) {
|
||||
case 'u':
|
||||
$userid = (int) $ugid;
|
||||
$override = $DB->get_record(
|
||||
'quiz_overrides',
|
||||
['quiz' => $quizid, 'userid' => $userid],
|
||||
'timeopen, timeclose, timelimit, attempts, password'
|
||||
);
|
||||
break;
|
||||
case 'g':
|
||||
$groupid = (int) $ugid;
|
||||
$override = $DB->get_record(
|
||||
'quiz_overrides',
|
||||
['quiz' => $quizid, 'groupid' => $groupid],
|
||||
'timeopen, timeclose, timelimit, attempts, password'
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \coding_exception('Invalid cache key');
|
||||
}
|
||||
|
||||
// Return null instead of false, because false will not be cached.
|
||||
return $override ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads several keys for the cache.
|
||||
*
|
||||
* @param array $keys An array of keys each of which will be string|int.
|
||||
* @return array An array of matching data items.
|
||||
*/
|
||||
public function load_many_for_cache(array $keys) {
|
||||
$results = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$results[] = $this->load_for_cache($key);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
35
mod/quiz/db/caches.php
Normal file
35
mod/quiz/db/caches.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Defined caches used internally by the plugin.
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2021 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$definitions = [
|
||||
'overrides' => [
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'simplekeys' => true,
|
||||
'datasource' => '\mod_quiz\cache\overrides',
|
||||
],
|
||||
];
|
@ -131,6 +131,7 @@ $string['browsersecurity_help'] = 'If "Full screen pop-up with some JavaScript s
|
||||
* The quiz will only start if the student has a JavaScript-enabled web-browser
|
||||
* The quiz appears in a full screen popup window that covers all the other windows and has no navigation controls
|
||||
* Students are prevented, as far as is possible, from using facilities like copy and paste';
|
||||
$string['cachedef_overrides'] = 'User and group override information';
|
||||
$string['calculated'] = 'Calculated';
|
||||
$string['calculatedquestion'] = 'Calculated question not supported at line {$a}. The question will be ignored';
|
||||
$string['cannotcreatepath'] = 'Path cannot be created ({$a})';
|
||||
|
@ -232,10 +232,12 @@ function quiz_delete_override($quiz, $overrideid, $log = true) {
|
||||
// Create the search array for a group override.
|
||||
$eventsearcharray = array('modulename' => 'quiz',
|
||||
'instance' => $quiz->id, 'groupid' => (int)$override->groupid);
|
||||
$cachekey = "{$quiz->id}_g_{$override->groupid}";
|
||||
} else {
|
||||
// Create the search array for a user override.
|
||||
$eventsearcharray = array('modulename' => 'quiz',
|
||||
'instance' => $quiz->id, 'userid' => (int)$override->userid);
|
||||
$cachekey = "{$quiz->id}_u_{$override->userid}";
|
||||
}
|
||||
$events = $DB->get_records('event', $eventsearcharray);
|
||||
foreach ($events as $event) {
|
||||
@ -244,6 +246,7 @@ function quiz_delete_override($quiz, $overrideid, $log = true) {
|
||||
}
|
||||
|
||||
$DB->delete_records('quiz_overrides', array('id' => $overrideid));
|
||||
cache::make('mod_quiz', 'overrides')->delete($cachekey);
|
||||
|
||||
if ($log) {
|
||||
// Set the common parameters for one of the events we will be triggering.
|
||||
@ -1536,6 +1539,8 @@ function quiz_reset_userdata($data) {
|
||||
'error' => false);
|
||||
}
|
||||
|
||||
$purgeoverrides = false;
|
||||
|
||||
// Remove user overrides.
|
||||
if (!empty($data->reset_quiz_user_overrides)) {
|
||||
$DB->delete_records_select('quiz_overrides',
|
||||
@ -1544,6 +1549,7 @@ function quiz_reset_userdata($data) {
|
||||
'component' => $componentstr,
|
||||
'item' => get_string('useroverridesdeleted', 'quiz'),
|
||||
'error' => false);
|
||||
$purgeoverrides = true;
|
||||
}
|
||||
// Remove group overrides.
|
||||
if (!empty($data->reset_quiz_group_overrides)) {
|
||||
@ -1553,6 +1559,7 @@ function quiz_reset_userdata($data) {
|
||||
'component' => $componentstr,
|
||||
'item' => get_string('groupoverridesdeleted', 'quiz'),
|
||||
'error' => false);
|
||||
$purgeoverrides = true;
|
||||
}
|
||||
|
||||
// Updating dates - shift may be negative too.
|
||||
@ -1566,6 +1573,8 @@ function quiz_reset_userdata($data) {
|
||||
WHERE quiz IN (SELECT id FROM {quiz} WHERE course = ?)
|
||||
AND timeclose <> 0", array($data->timeshift, $data->courseid));
|
||||
|
||||
$purgeoverrides = true;
|
||||
|
||||
// Any changes to the list of dates that needs to be rolled should be same during course restore and course reset.
|
||||
// See MDL-9367.
|
||||
shift_course_mod_dates('quiz', array('timeopen', 'timeclose'),
|
||||
@ -1577,6 +1586,10 @@ function quiz_reset_userdata($data) {
|
||||
'error' => false);
|
||||
}
|
||||
|
||||
if ($purgeoverrides) {
|
||||
cache::make('mod_quiz', 'overrides')->purge();
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
|
@ -1923,7 +1923,7 @@ function quiz_process_group_deleted_in_course($courseid) {
|
||||
|
||||
// It would be nice if we got the groupid that was deleted.
|
||||
// Instead, we just update all quizzes with orphaned group overrides.
|
||||
$sql = "SELECT o.id, o.quiz
|
||||
$sql = "SELECT o.id, o.quiz, o.groupid
|
||||
FROM {quiz_overrides} o
|
||||
JOIN {quiz} quiz ON quiz.id = o.quiz
|
||||
LEFT JOIN {groups} grp ON grp.id = o.groupid
|
||||
@ -1931,12 +1931,16 @@ function quiz_process_group_deleted_in_course($courseid) {
|
||||
AND o.groupid IS NOT NULL
|
||||
AND grp.id IS NULL";
|
||||
$params = array('courseid' => $courseid);
|
||||
$records = $DB->get_records_sql_menu($sql, $params);
|
||||
$records = $DB->get_records_sql($sql, $params);
|
||||
if (!$records) {
|
||||
return; // Nothing to do.
|
||||
}
|
||||
$DB->delete_records_list('quiz_overrides', 'id', array_keys($records));
|
||||
quiz_update_open_attempts(array('quizid' => array_unique(array_values($records))));
|
||||
$cache = cache::make('mod_quiz', 'overrides');
|
||||
foreach ($records as $record) {
|
||||
$cache->delete("{$record->quiz}_g_{$record->groupid}");
|
||||
}
|
||||
quiz_update_open_attempts(['quizid' => array_unique(array_column($records, 'quiz'))]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,6 +176,8 @@ if ($mform->is_cancelled()) {
|
||||
if (!empty($override->id)) {
|
||||
$fromform->id = $override->id;
|
||||
$DB->update_record('quiz_overrides', $fromform);
|
||||
$cachekey = $groupmode ? "{$fromform->quiz}_g_{$fromform->groupid}" : "{$fromform->quiz}_u_{$fromform->userid}";
|
||||
cache::make('mod_quiz', 'overrides')->delete($cachekey);
|
||||
|
||||
// Determine which override updated event to fire.
|
||||
$params['objectid'] = $override->id;
|
||||
@ -192,6 +194,8 @@ if ($mform->is_cancelled()) {
|
||||
} else {
|
||||
unset($fromform->id);
|
||||
$fromform->id = $DB->insert_record('quiz_overrides', $fromform);
|
||||
$cachekey = $groupmode ? "{$fromform->quiz}_g_{$fromform->groupid}" : "{$fromform->quiz}_u_{$fromform->userid}";
|
||||
cache::make('mod_quiz', 'overrides')->delete($cachekey);
|
||||
|
||||
// Determine which override created event to fire.
|
||||
$params['objectid'] = $fromform->id;
|
||||
|
@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2021052501;
|
||||
$plugin->version = 2021052502;
|
||||
$plugin->requires = 2021052500;
|
||||
$plugin->component = 'mod_quiz';
|
||||
|
Loading…
x
Reference in New Issue
Block a user