diff --git a/mod/quiz/classes/event/slot_version_updated.php b/mod/quiz/classes/event/slot_version_updated.php new file mode 100644 index 0000000000000..92625d8fbae38 --- /dev/null +++ b/mod/quiz/classes/event/slot_version_updated.php @@ -0,0 +1,94 @@ +. + +declare(strict_types=1); + +namespace mod_quiz\event; + +/** + * The question version of a slot has changed. + * + * @property-read array $other { + * Extra information about event. + * + * - int quizid: the id of the quiz. + * - int previousversion: the previous question version. + * - int newversion: the new question version. + * } + * + * @package mod_quiz + * @copyright 2024 Catalyst IT Australia Pty Ltd + * @author Cameron Ball + * @license https://gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class slot_version_updated extends \core\event\base { + protected function init() { + $this->data['objecttable'] = 'quiz_slots'; + $this->data['crud'] = 'u'; + $this->data['edulevel'] = self::LEVEL_TEACHING; + } + + public static function get_name() { + return get_string('eventslotversionupdated', 'mod_quiz'); + } + + public function get_description() { + return "The user with id '$this->userid' updated the slot with id '{$this->objectid}' " . + "belonging to the quiz with course module id '$this->contextinstanceid'. " . + "Its qeustion version was changed from '{$this->other['previousversion']}' to '{$this->other['newversion']}'."; + } + + public function get_url() { + return new \moodle_url('/mod/quiz/edit.php', [ + 'cmid' => $this->contextinstanceid + ]); + } + + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->objectid)) { + throw new \coding_exception('The \'objectid\' value must be set.'); + } + + if (!isset($this->contextinstanceid)) { + throw new \coding_exception('The \'contextinstanceid\' value must be set.'); + } + + if (!isset($this->other['quizid'])) { + throw new \coding_exception('The \'quizid\' value must be set in other.'); + } + + if (!isset($this->other['previousversion'])) { + throw new \coding_exception('The \'previousversion\' value must be set in other.'); + } + + if (!isset($this->other['newversion'])) { + throw new \coding_exception('The \'newversion\' value must be set in other.'); + } + } + + public static function get_objectid_mapping() { + return ['db' => 'quiz_slots', 'restore' => 'quiz_question_instance']; + } + + public static function get_other_mapping() { + $othermapped = []; + $othermapped['quizid'] = ['db' => 'quiz', 'restore' => 'quiz']; + + return $othermapped; + } +} diff --git a/mod/quiz/classes/external/submit_question_version.php b/mod/quiz/classes/external/submit_question_version.php index 5facc34a8e7b1..e640f98849afe 100644 --- a/mod/quiz/classes/external/submit_question_version.php +++ b/mod/quiz/classes/external/submit_question_version.php @@ -22,10 +22,13 @@ require_once($CFG->dirroot . '/question/engine/datalib.php'); require_once($CFG->libdir . '/questionlib.php'); +use core\context\module; use core_external\external_api; use core_external\external_function_parameters; use core_external\external_single_structure; use core_external\external_value; +use mod_quiz\quiz_settings; +use mod_quiz\structure; use stdClass; /** @@ -59,32 +62,15 @@ public static function execute_parameters(): external_function_parameters { */ public static function execute(int $slotid, int $newversion): array { global $DB; - $params = [ - 'slotid' => $slotid, - 'newversion' => $newversion - ]; - $params = self::validate_parameters(self::execute_parameters(), $params); - $response = []; - // Get the required data. - $referencedata = $DB->get_record('question_references', - ['itemid' => $params['slotid'], 'component' => 'mod_quiz', 'questionarea' => 'slot']); - $slotdata = $DB->get_record('quiz_slots', ['id' => $slotid]); + $params = self::validate_parameters(self::execute_parameters(), ['slotid' => $slotid, 'newversion' => $newversion]); + $slot = $DB->get_record('quiz_slots', ['id' => $slotid], '*', MUST_EXIST); - // Capability check. - [, $cm] = get_course_and_cm_from_instance($slotdata->quizid, 'quiz'); - $context = \context_module::instance($cm->id); + $context = module::instance(get_course_and_cm_from_instance($slot->quizid, 'quiz')[1]->id); self::validate_context($context); require_capability('mod/quiz:manage', $context); - $reference = new stdClass(); - $reference->id = $referencedata->id; - if ($params['newversion'] === 0) { - $reference->version = null; - } else { - $reference->version = $params['newversion']; - } - $response['result'] = $DB->update_record('question_references', $reference); - return $response; + $quizobj = quiz_settings::create($slot->quizid); + return ['result' => $quizobj->get_structure()->update_slot_version($slot, $params['newversion'])]; } /** diff --git a/mod/quiz/classes/structure.php b/mod/quiz/classes/structure.php index 15a72d372d145..49f6713043652 100644 --- a/mod/quiz/classes/structure.php +++ b/mod/quiz/classes/structure.php @@ -24,6 +24,7 @@ use mod_quiz\event\quiz_grade_item_updated; use mod_quiz\event\slot_grade_item_updated; use mod_quiz\event\slot_mark_updated; +use mod_quiz\event\slot_version_updated; use mod_quiz\question\bank\qbank_helper; use mod_quiz\question\qubaids_for_quiz; use stdClass; @@ -1168,6 +1169,34 @@ public function update_slot_maxmark($slot, $maxmark) { return true; } + /** + * Update slot question version. + * + * @param stdClass $slot Row from the quiz_slots table. + * @param int $newversion The new question version for the slot. + * @return bool + */ + public function update_slot_version(stdClass $slot, int $newversion): bool { + global $DB; + + $params = ['itemid' => $slot->id, 'component' => 'mod_quiz', 'questionarea' => 'slot']; + $reference = $DB->get_record('question_references', $params, '*', MUST_EXIST); + $oldversion = $reference->version; + $reference->version = $newversion === 0 ? null : $newversion; + + slot_version_updated::create([ + 'context' => $this->quizobj->get_context(), + 'objectid' => $slot->id, + 'other' => [ + 'quizid' => $this->get_quizid(), + 'previousversion' => $oldversion, + 'newversion' => $newversion, + ], + ])->trigger(); + + return $DB->update_record('question_references', $reference); + } + /** * Change which grade this slot contributes to, for quizzes with multiple grades. * diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index 25d56edff470e..f7909ff2efa05 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -390,6 +390,7 @@ $string['eventslotdisplayedquestionnumberupdated'] = 'Slot displayed question number updated'; $string['eventslotgradeitemupdated'] = 'Slot grade item updated'; $string['eventslotmarkupdated'] = 'Slot mark updated'; +$string['eventslotversionupdated'] = 'Slot version updated'; $string['eventslotmoved'] = 'Slot moved'; $string['eventslotrequirepreviousupdated'] = 'Slot require previous updated'; $string['everynquestions'] = 'Every {$a} questions'; diff --git a/mod/quiz/version.php b/mod/quiz/version.php index fa22a93ba4087..c0b9aa1a833ed 100644 --- a/mod/quiz/version.php +++ b/mod/quiz/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024051700; +$plugin->version = 2024072500; $plugin->requires = 2024041600; $plugin->component = 'mod_quiz';