mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
Merge branch 'MDL-75301_master' of https://github.com/marxjohnson/moodle
This commit is contained in:
commit
34ab6b02d9
@ -28,6 +28,7 @@ use core_question\local\bank\question_version_status;
|
|||||||
use mod_quiz\question\bank\qbank_helper;
|
use mod_quiz\question\bank\qbank_helper;
|
||||||
use \mod_quiz\structure;
|
use \mod_quiz\structure;
|
||||||
use \html_writer;
|
use \html_writer;
|
||||||
|
use qbank_previewquestion\question_preview_options;
|
||||||
use renderable;
|
use renderable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -838,11 +839,12 @@ class edit_renderer extends \plugin_renderer_base {
|
|||||||
public function get_action_icon(structure $structure, int $slot, \moodle_url $pageurl) : string {
|
public function get_action_icon(structure $structure, int $slot, \moodle_url $pageurl) : string {
|
||||||
// Action icons.
|
// Action icons.
|
||||||
$qtype = $structure->get_question_type_for_slot($slot);
|
$qtype = $structure->get_question_type_for_slot($slot);
|
||||||
|
$slotinfo = $structure->get_slot_by_number($slot);
|
||||||
$questionicons = '';
|
$questionicons = '';
|
||||||
if ($qtype !== 'random') {
|
if ($qtype !== 'random') {
|
||||||
$questionicons .= $this->question_preview_icon($structure->get_quiz(),
|
$questionicons .= $this->question_preview_icon($structure->get_quiz(),
|
||||||
$structure->get_question_in_slot($slot),
|
$structure->get_question_in_slot($slot),
|
||||||
null, null, $qtype);
|
null, null, $slotinfo->requestedversion ?: question_preview_options::ALWAYS_LATEST);
|
||||||
}
|
}
|
||||||
if ($structure->can_be_edited() && $structure->has_use_capability($slot)) {
|
if ($structure->can_be_edited() && $structure->has_use_capability($slot)) {
|
||||||
$questionicons .= $this->question_remove_icon($structure, $slot, $pageurl);
|
$questionicons .= $this->question_remove_icon($structure, $slot, $pageurl);
|
||||||
@ -890,16 +892,17 @@ class edit_renderer extends \plugin_renderer_base {
|
|||||||
* If ->questionid is set, that is used instead of ->id.
|
* If ->questionid is set, that is used instead of ->id.
|
||||||
* @param bool $label if true, show the preview question label after the icon
|
* @param bool $label if true, show the preview question label after the icon
|
||||||
* @param int $variant which question variant to preview (optional).
|
* @param int $variant which question variant to preview (optional).
|
||||||
|
* @param int $restartversion version to use when restarting the preview
|
||||||
* @return string HTML to output.
|
* @return string HTML to output.
|
||||||
*/
|
*/
|
||||||
public function question_preview_icon($quiz, $questiondata, $label = null, $variant = null) {
|
public function question_preview_icon($quiz, $questiondata, $label = null, $variant = null, $restartversion = null) {
|
||||||
$question = clone($questiondata);
|
$question = clone($questiondata);
|
||||||
if (isset($question->questionid)) {
|
if (isset($question->questionid)) {
|
||||||
|
|
||||||
$question->id = $question->questionid;
|
$question->id = $question->questionid;
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = quiz_question_preview_url($quiz, $question, $variant);
|
$url = quiz_question_preview_url($quiz, $question, $variant, $restartversion);
|
||||||
|
|
||||||
// Do we want a label?
|
// Do we want a label?
|
||||||
$strpreviewlabel = '';
|
$strpreviewlabel = '';
|
||||||
|
@ -1049,9 +1049,10 @@ function quiz_question_edit_button($cmid, $question, $returnurl, $contentafteric
|
|||||||
* @param stdClass $quiz the quiz settings
|
* @param stdClass $quiz the quiz settings
|
||||||
* @param stdClass $question the question
|
* @param stdClass $question the question
|
||||||
* @param int $variant which question variant to preview (optional).
|
* @param int $variant which question variant to preview (optional).
|
||||||
|
* @param int $restartversion version of the question to use when restarting the preview.
|
||||||
* @return moodle_url to preview this question with the options from this quiz.
|
* @return moodle_url to preview this question with the options from this quiz.
|
||||||
*/
|
*/
|
||||||
function quiz_question_preview_url($quiz, $question, $variant = null) {
|
function quiz_question_preview_url($quiz, $question, $variant = null, $restartversion = null) {
|
||||||
// Get the appropriate display options.
|
// Get the appropriate display options.
|
||||||
$displayoptions = display_options::make_from_quiz($quiz,
|
$displayoptions = display_options::make_from_quiz($quiz,
|
||||||
display_options::DURING);
|
display_options::DURING);
|
||||||
@ -1063,7 +1064,7 @@ function quiz_question_preview_url($quiz, $question, $variant = null) {
|
|||||||
|
|
||||||
// Work out the correcte preview URL.
|
// Work out the correcte preview URL.
|
||||||
return \qbank_previewquestion\helper::question_preview_url($question->id, $quiz->preferredbehaviour,
|
return \qbank_previewquestion\helper::question_preview_url($question->id, $quiz->preferredbehaviour,
|
||||||
$maxmark, $displayoptions, $variant);
|
$maxmark, $displayoptions, $variant, null, null, $restartversion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1079,7 +1080,10 @@ function quiz_question_preview_button($quiz, $question, $label = false, $variant
|
|||||||
if (!question_has_capability_on($question, 'use')) {
|
if (!question_has_capability_on($question, 'use')) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return $PAGE->get_renderer('mod_quiz', 'edit')->question_preview_icon($quiz, $question, $label, $variant, null);
|
$slotinfo = quiz_settings::create($quiz->id)->get_structure()->get_slot_by_number($question->slot);
|
||||||
|
return $PAGE->get_renderer('mod_quiz', 'edit')
|
||||||
|
->question_preview_icon($quiz, $question, $label, $variant,
|
||||||
|
$slotinfo->requestedversion ?: \qbank_previewquestion\question_preview_options::ALWAYS_LATEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,3 +121,19 @@ Feature: Quiz question versioning
|
|||||||
And I set the field "question_status_dropdown" in the "First question" "table_row" to "Draft"
|
And I set the field "question_status_dropdown" in the "First question" "table_row" to "Draft"
|
||||||
When I am on the "Quiz 1" "mod_quiz > Edit" page
|
When I am on the "Quiz 1" "mod_quiz > Edit" page
|
||||||
Then I should see "This question has all versions in Draft status. The quiz will not work with this question in place."
|
Then I should see "This question has all versions in Draft status. The quiz will not work with this question in place."
|
||||||
|
|
||||||
|
@javascript
|
||||||
|
Scenario: Previewing a question set to use always latest version will set the preview to always latest version
|
||||||
|
When I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher"
|
||||||
|
And the field "version" in the "First question" "list_item" matches value "Always latest"
|
||||||
|
When I follow "Preview question"
|
||||||
|
And I expand all fieldsets
|
||||||
|
Then the field "Question version" matches value "Always latest"
|
||||||
|
|
||||||
|
@javascript
|
||||||
|
Scenario: Previewing a question set to use a specific version will set the preview to that version
|
||||||
|
When I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher"
|
||||||
|
And I set the field "version" to "v1 (latest)"
|
||||||
|
When I follow "Preview question"
|
||||||
|
And I expand all fieldsets
|
||||||
|
Then the field "Question version" matches value "1"
|
||||||
|
@ -196,4 +196,8 @@ class question_history_view extends view {
|
|||||||
echo $PAGE->get_renderer('qbank_history')->render_history_header($historydata);
|
echo $PAGE->get_renderer('qbank_history')->render_history_header($historydata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function is_listing_specific_versions(): bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ require_once($CFG->libdir . '/formslib.php');
|
|||||||
use moodleform;
|
use moodleform;
|
||||||
use question_display_options;
|
use question_display_options;
|
||||||
use question_engine;
|
use question_engine;
|
||||||
|
use qbank_previewquestion\question_preview_options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings form for the preview options.
|
* Settings form for the preview options.
|
||||||
@ -45,8 +46,9 @@ class preview_options_form extends moodleform {
|
|||||||
$mform->addElement('header', 'attemptoptionsheader', get_string('previewoptions', 'qbank_previewquestion'));
|
$mform->addElement('header', 'attemptoptionsheader', get_string('previewoptions', 'qbank_previewquestion'));
|
||||||
$mform->setExpanded('attemptoptionsheader', false);
|
$mform->setExpanded('attemptoptionsheader', false);
|
||||||
$versions = $this->_customdata['versions'];
|
$versions = $this->_customdata['versions'];
|
||||||
$currentversion = $this->_customdata['questionversion'];
|
$versions[question_preview_options::ALWAYS_LATEST] = get_string('alwayslatest', 'qbank_previewquestion');
|
||||||
$select = $mform->addElement('select', 'version', get_string('questionversion', 'qbank_previewquestion'), $versions);
|
$currentversion = $this->_customdata['restartversion'];
|
||||||
|
$select = $mform->addElement('select', 'restartversion', get_string('questionversion', 'qbank_previewquestion'), $versions);
|
||||||
$select->setSelected($currentversion);
|
$select->setSelected($currentversion);
|
||||||
$behaviours = question_engine::get_behaviour_options(
|
$behaviours = question_engine::get_behaviour_options(
|
||||||
$this->_customdata['quba']->get_preferred_behaviour());
|
$this->_customdata['quba']->get_preferred_behaviour());
|
||||||
|
@ -103,10 +103,11 @@ class helper {
|
|||||||
* @param question_preview_options $options the options in use
|
* @param question_preview_options $options the options in use
|
||||||
* @param context $context context for the question preview
|
* @param context $context context for the question preview
|
||||||
* @param moodle_url $returnurl url of the page to return to
|
* @param moodle_url $returnurl url of the page to return to
|
||||||
|
* @param int|null $restartversion version of the question to use when next restarting the preview.
|
||||||
* @return moodle_url
|
* @return moodle_url
|
||||||
*/
|
*/
|
||||||
public static function question_preview_action_url($questionid, $qubaid,
|
public static function question_preview_action_url($questionid, $qubaid,
|
||||||
question_preview_options $options, $context, $returnurl = null): moodle_url {
|
question_preview_options $options, $context, $returnurl = null, $restartversion = null): moodle_url {
|
||||||
$params = [
|
$params = [
|
||||||
'id' => $questionid,
|
'id' => $questionid,
|
||||||
'previewid' => $qubaid,
|
'previewid' => $qubaid,
|
||||||
@ -119,6 +120,9 @@ class helper {
|
|||||||
if ($returnurl !== null) {
|
if ($returnurl !== null) {
|
||||||
$params['returnurl'] = $returnurl;
|
$params['returnurl'] = $returnurl;
|
||||||
}
|
}
|
||||||
|
if ($restartversion !== null) {
|
||||||
|
$params['restartversion'] = $restartversion;
|
||||||
|
}
|
||||||
$params = array_merge($params, $options->get_url_params());
|
$params = array_merge($params, $options->get_url_params());
|
||||||
return new moodle_url('/question/bank/previewquestion/preview.php', $params);
|
return new moodle_url('/question/bank/previewquestion/preview.php', $params);
|
||||||
}
|
}
|
||||||
@ -158,10 +162,11 @@ class helper {
|
|||||||
* @param object $displayoptions display options for the question in preview
|
* @param object $displayoptions display options for the question in preview
|
||||||
* @param object $context context of the question for preview
|
* @param object $context context of the question for preview
|
||||||
* @param moodle_url $returnurl url of the page to return to
|
* @param moodle_url $returnurl url of the page to return to
|
||||||
* @param int|null $version version of the question in preview
|
* @param int|null $restartversion version of the question to use when next restarting the preview.
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function restart_preview($previewid, $questionid, $displayoptions, $context,
|
public static function restart_preview($previewid, $questionid, $displayoptions, $context,
|
||||||
$returnurl = null, $version = null): void {
|
$returnurl = null, $restartversion = null): void {
|
||||||
global $DB;
|
global $DB;
|
||||||
|
|
||||||
if ($previewid) {
|
if ($previewid) {
|
||||||
@ -170,7 +175,8 @@ class helper {
|
|||||||
$transaction->allow_commit();
|
$transaction->allow_commit();
|
||||||
}
|
}
|
||||||
redirect(self::question_preview_url($questionid, $displayoptions->behaviour,
|
redirect(self::question_preview_url($questionid, $displayoptions->behaviour,
|
||||||
$displayoptions->maxmark, $displayoptions, $displayoptions->variant, $context, $returnurl, $version));
|
$displayoptions->maxmark, $displayoptions, $displayoptions->variant,
|
||||||
|
$context, $returnurl, $restartversion));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -185,17 +191,17 @@ class helper {
|
|||||||
* @param object $context context to run the preview in (affects things like
|
* @param object $context context to run the preview in (affects things like
|
||||||
* filter settings, theme, lang, etc.) Defaults to $PAGE->context
|
* filter settings, theme, lang, etc.) Defaults to $PAGE->context
|
||||||
* @param moodle_url $returnurl url of the page to return to
|
* @param moodle_url $returnurl url of the page to return to
|
||||||
* @param int $version version of the question
|
* @param int $restartversion The version of the question to use when restarting the preview.
|
||||||
* @return moodle_url the URL
|
* @return moodle_url the URL
|
||||||
*/
|
*/
|
||||||
public static function question_preview_url($questionid, $preferredbehaviour = null,
|
public static function question_preview_url($questionid, $preferredbehaviour = null,
|
||||||
$maxmark = null, $displayoptions = null, $variant = null, $context = null, $returnurl = null,
|
$maxmark = null, $displayoptions = null, $variant = null, $context = null, $returnurl = null,
|
||||||
$version = null): moodle_url {
|
$restartversion = null): moodle_url {
|
||||||
|
|
||||||
$params = ['id' => $questionid];
|
$params = ['id' => $questionid];
|
||||||
|
|
||||||
if (!is_null($version)) {
|
if (!is_null($restartversion)) {
|
||||||
$params['id'] = $version;
|
$params['restartversion'] = $restartversion;
|
||||||
}
|
}
|
||||||
if (is_null($context)) {
|
if (is_null($context)) {
|
||||||
global $PAGE;
|
global $PAGE;
|
||||||
@ -313,4 +319,21 @@ class helper {
|
|||||||
}
|
}
|
||||||
return $questionids;
|
return $questionids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the question ID from the array of id => version that corresponds to the requested version.
|
||||||
|
*
|
||||||
|
* If the requested version is question_preview_options::ALWAYS_LATEST, this will return the latest version.
|
||||||
|
*
|
||||||
|
* @param array $versions
|
||||||
|
* @param int $restartversion
|
||||||
|
* @return ?int
|
||||||
|
*/
|
||||||
|
public static function get_restart_id(array $versions, int $restartversion): ?int {
|
||||||
|
if ($restartversion === question_preview_options::ALWAYS_LATEST) {
|
||||||
|
return array_key_last($versions);
|
||||||
|
} else {
|
||||||
|
return array_search($restartversion, $versions) ?: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace qbank_previewquestion\output;
|
|||||||
|
|
||||||
use context;
|
use context;
|
||||||
use qbank_previewquestion\helper;
|
use qbank_previewquestion\helper;
|
||||||
|
use qbank_previewquestion\question_preview_options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class renderer for rendering preview url
|
* Class renderer for rendering preview url
|
||||||
@ -50,7 +51,8 @@ class renderer extends \plugin_renderer_base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$image = $this->pix_icon('t/preview', $alt, '', ['class' => 'iconsmall']);
|
$image = $this->pix_icon('t/preview', $alt, '', ['class' => 'iconsmall']);
|
||||||
$link = helper::question_preview_url($questionid, null, null, null, null, $context);
|
$link = helper::question_preview_url($questionid, null, null, null, null, $context, null,
|
||||||
|
question_preview_options::ALWAYS_LATEST);
|
||||||
$action = new \popup_action('click', $link, 'questionpreview', helper::question_preview_popup_params());
|
$action = new \popup_action('click', $link, 'questionpreview', helper::question_preview_popup_params());
|
||||||
|
|
||||||
return $this->action_link($link, $image . $label, $action, $attributes);
|
return $this->action_link($link, $image . $label, $action, $attributes);
|
||||||
|
@ -52,8 +52,15 @@ class preview_action_column extends menu_action_column_base {
|
|||||||
|
|
||||||
if (question_has_capability_on($question, 'use')) {
|
if (question_has_capability_on($question, 'use')) {
|
||||||
$context = $this->qbank->get_most_specific_context();
|
$context = $this->qbank->get_most_specific_context();
|
||||||
|
// Default previews to always use the latest question version, unless we are previewing specific versions from the
|
||||||
|
// question history.
|
||||||
|
if ($this->qbank->is_listing_specific_versions()) {
|
||||||
|
$requestedversion = $question->version;
|
||||||
|
} else {
|
||||||
|
$requestedversion = question_preview_options::ALWAYS_LATEST;
|
||||||
|
}
|
||||||
$url = helper::question_preview_url($question->id, null, null,
|
$url = helper::question_preview_url($question->id, null, null,
|
||||||
null, null, $context, $this->qbank->returnurl);
|
null, null, $context, $this->qbank->returnurl, $requestedversion);
|
||||||
return [$url, 't/preview', $this->strpreview];
|
return [$url, 't/preview', $this->strpreview];
|
||||||
} else {
|
} else {
|
||||||
return [null, null, null];
|
return [null, null, null];
|
||||||
|
@ -42,6 +42,9 @@ class question_preview_options extends question_display_options {
|
|||||||
/** @var string prefix to append to field names to get user_preference names. */
|
/** @var string prefix to append to field names to get user_preference names. */
|
||||||
const OPTIONPREFIX = 'question_preview_options_';
|
const OPTIONPREFIX = 'question_preview_options_';
|
||||||
|
|
||||||
|
/** @var int Special value for question version ID to indicate that we should always use the latest version */
|
||||||
|
const ALWAYS_LATEST = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param \stdClass $question
|
* @param \stdClass $question
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$string['alwayslatest'] = 'Always latest';
|
||||||
|
$string['newerversion'] = 'This preview is using version {$a->currentversion} of this question. '
|
||||||
|
. 'The latest version is {$a->latestversion}. {$a->restartbutton}?';
|
||||||
$string['pluginname'] = 'Preview question';
|
$string['pluginname'] = 'Preview question';
|
||||||
$string['privacy:metadata'] = 'The Preview question question bank plugin does not store any personal data.';
|
$string['privacy:metadata'] = 'The Preview question question bank plugin does not store any personal data.';
|
||||||
// Tag related errors.
|
// Tag related errors.
|
||||||
@ -32,6 +35,7 @@ $string['tagsnotfound'] = 'Tags not found';
|
|||||||
// Form string(s).
|
// Form string(s).
|
||||||
$string['previewoptions'] = 'Preview options';
|
$string['previewoptions'] = 'Preview options';
|
||||||
$string['questionversion'] = 'Question version';
|
$string['questionversion'] = 'Question version';
|
||||||
|
$string['restartnow'] = 'Restart now';
|
||||||
// Preview title.
|
// Preview title.
|
||||||
$string['versiontitle'] = 'Version {$a}';
|
$string['versiontitle'] = 'Version {$a}';
|
||||||
$string['versiontitlelatest'] = 'Version {$a} (latest)';
|
$string['versiontitlelatest'] = 'Version {$a} (latest)';
|
||||||
|
@ -49,6 +49,7 @@ define('QUESTION_PREVIEW_MAX_VARIANTS', 100);
|
|||||||
// Get and validate question id.
|
// Get and validate question id.
|
||||||
$id = required_param('id', PARAM_INT);
|
$id = required_param('id', PARAM_INT);
|
||||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||||
|
$restartversion = optional_param('restartversion', question_preview_options::ALWAYS_LATEST, PARAM_INT);
|
||||||
|
|
||||||
$question = question_bank::load_question($id);
|
$question = question_bank::load_question($id);
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ $options = new question_preview_options($question);
|
|||||||
$options->load_user_defaults();
|
$options->load_user_defaults();
|
||||||
$options->set_from_request();
|
$options->set_from_request();
|
||||||
$PAGE->set_url(helper::question_preview_url($id, $options->behaviour, $options->maxmark,
|
$PAGE->set_url(helper::question_preview_url($id, $options->behaviour, $options->maxmark,
|
||||||
$options, $options->variant, $context));
|
$options, $options->variant, $context, null, $restartversion));
|
||||||
|
|
||||||
// Get and validate existing preview, or start a new one.
|
// Get and validate existing preview, or start a new one.
|
||||||
$previewid = optional_param('previewid', 0, PARAM_INT);
|
$previewid = optional_param('previewid', 0, PARAM_INT);
|
||||||
@ -97,7 +98,7 @@ if ($previewid) {
|
|||||||
// actually from the user point of view, it makes sense.
|
// actually from the user point of view, it makes sense.
|
||||||
throw new moodle_exception('submissionoutofsequencefriendlymessage', 'question',
|
throw new moodle_exception('submissionoutofsequencefriendlymessage', 'question',
|
||||||
helper::question_preview_url($question->id, $options->behaviour,
|
helper::question_preview_url($question->id, $options->behaviour,
|
||||||
$options->maxmark, $options, $options->variant, $context), null, $e);
|
$options->maxmark, $options, $options->variant, $context, null, $restartversion), null, $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($quba->get_owning_context()->instanceid != $USER->id) {
|
if ($quba->get_owning_context()->instanceid != $USER->id) {
|
||||||
@ -133,11 +134,15 @@ if ($previewid) {
|
|||||||
$options->behaviour = $quba->get_preferred_behaviour();
|
$options->behaviour = $quba->get_preferred_behaviour();
|
||||||
$options->maxmark = $quba->get_question_max_mark($slot);
|
$options->maxmark = $quba->get_question_max_mark($slot);
|
||||||
|
|
||||||
// Create the settings form, and initialise the fields.
|
|
||||||
$versionids = helper::load_versions($question->questionbankentryid);
|
$versionids = helper::load_versions($question->questionbankentryid);
|
||||||
$optionsform = new preview_options_form(helper::
|
// Create the settings form, and initialise the fields.
|
||||||
question_preview_form_url($question->id, $context, $previewid, $returnurl),
|
$optionsform = new preview_options_form(helper::question_preview_form_url($question->id, $context, $previewid, $returnurl),
|
||||||
['quba' => $quba, 'maxvariant' => $maxvariant, 'versions' => $versionids, 'questionversion' => $id]);
|
[
|
||||||
|
'quba' => $quba,
|
||||||
|
'maxvariant' => $maxvariant,
|
||||||
|
'versions' => array_combine(array_values($versionids), array_values($versionids)),
|
||||||
|
'restartversion' => $restartversion,
|
||||||
|
]);
|
||||||
$optionsform->set_data($options);
|
$optionsform->set_data($options);
|
||||||
|
|
||||||
// Process change of settings, if that was requested.
|
// Process change of settings, if that was requested.
|
||||||
@ -147,13 +152,14 @@ if ($newoptions = $optionsform->get_submitted_data()) {
|
|||||||
if (!isset($newoptions->variant)) {
|
if (!isset($newoptions->variant)) {
|
||||||
$newoptions->variant = $options->variant;
|
$newoptions->variant = $options->variant;
|
||||||
}
|
}
|
||||||
|
$questionid = helper::get_restart_id($versionids, $restartversion);
|
||||||
if (isset($newoptions->saverestart)) {
|
if (isset($newoptions->saverestart)) {
|
||||||
helper::restart_preview($previewid, $question->id, $newoptions, $context, $returnurl, $newoptions->version);
|
helper::restart_preview($previewid, $questionid, $newoptions, $context, $returnurl, $newoptions->restartversion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare a URL that is used in various places.
|
// Prepare a URL that is used in various places.
|
||||||
$actionurl = helper::question_preview_action_url($question->id, $quba->get_id(), $options, $context, $returnurl);
|
$actionurl = helper::question_preview_action_url($question->id, $quba->get_id(), $options, $context, $returnurl, $restartversion);
|
||||||
|
|
||||||
// Process any actions from the buttons at the bottom of the form.
|
// Process any actions from the buttons at the bottom of the form.
|
||||||
if (data_submitted() && confirm_sesskey()) {
|
if (data_submitted() && confirm_sesskey()) {
|
||||||
@ -161,7 +167,8 @@ if (data_submitted() && confirm_sesskey()) {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
if (optional_param('restart', false, PARAM_BOOL)) {
|
if (optional_param('restart', false, PARAM_BOOL)) {
|
||||||
helper::restart_preview($previewid, $question->id, $options, $context, $returnurl);
|
$questionid = helper::get_restart_id($versionids, $restartversion);
|
||||||
|
helper::restart_preview($previewid, $questionid, $options, $context, $returnurl, $restartversion);
|
||||||
|
|
||||||
} else if (optional_param('fill', null, PARAM_BOOL)) {
|
} else if (optional_param('fill', null, PARAM_BOOL)) {
|
||||||
$correctresponse = $quba->get_correct_response($slot);
|
$correctresponse = $quba->get_correct_response($slot);
|
||||||
@ -262,6 +269,17 @@ if ($islatestversion) {
|
|||||||
$previewdata['versiontitle'] = get_string('versiontitlelatest', 'qbank_previewquestion', $question->version);
|
$previewdata['versiontitle'] = get_string('versiontitlelatest', 'qbank_previewquestion', $question->version);
|
||||||
} else {
|
} else {
|
||||||
$previewdata['versiontitle'] = get_string('versiontitle', 'qbank_previewquestion', $question->version);
|
$previewdata['versiontitle'] = get_string('versiontitle', 'qbank_previewquestion', $question->version);
|
||||||
|
if ($restartversion == question_preview_options::ALWAYS_LATEST) {
|
||||||
|
$newerversionparams = (object) [
|
||||||
|
'currentversion' => $question->version,
|
||||||
|
'latestversion' => max($versionids),
|
||||||
|
'restartbutton' => $OUTPUT->render_from_template('qbank_previewquestion/restartbutton', []),
|
||||||
|
];
|
||||||
|
$newversionurl = clone $actionurl;
|
||||||
|
$newversionurl->param('restart', 1);
|
||||||
|
$previewdata['newerversionurl'] = $newversionurl;
|
||||||
|
$previewdata['newerversion'] = get_string('newerversion', 'qbank_previewquestion', $newerversionparams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$previewdata['actionurl'] = $actionurl;
|
$previewdata['actionurl'] = $actionurl;
|
||||||
|
@ -61,6 +61,11 @@
|
|||||||
<span class="badge bg-primary text-light">{{versiontitle}}</span>
|
<span class="badge bg-primary text-light">{{versiontitle}}</span>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
{{#newerversion}}
|
||||||
|
<div class="alert alert-primary">
|
||||||
|
{{{newerversion}}}
|
||||||
|
</div>
|
||||||
|
{{/newerversion}}
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="badge-primary h-50 px-2 mt-n2">
|
<div class="badge-primary h-50 px-2 mt-n2">
|
||||||
<span class="accesshide">ID number</span>
|
<span class="accesshide">ID number</span>
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
{{!
|
||||||
|
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/>.
|
||||||
|
}}
|
||||||
|
{{!
|
||||||
|
@template qbank_previewquestion/restartbutton
|
||||||
|
|
||||||
|
A button to restart the preview.
|
||||||
|
|
||||||
|
Example context (json):
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
<input type="submit" name="restart" value="{{#str}}restartnow, qbank_previewquestion{{/str}}"
|
||||||
|
class="btn btn-secondary" id="id_restartnow_question_preview">
|
@ -92,19 +92,75 @@ Feature: A teacher can preview questions in the question bank
|
|||||||
Then the field "Marked out of" matches value "0.00000123456789"
|
Then the field "Marked out of" matches value "0.00000123456789"
|
||||||
|
|
||||||
Scenario: Question version is updated when edited and teacher can change question version
|
Scenario: Question version is updated when edited and teacher can change question version
|
||||||
And I should see "Version 1"
|
Given I should see "Version 1"
|
||||||
And I press "Close preview"
|
And I press "Close preview"
|
||||||
And I choose "Edit question" action for "Test question to be previewed" in the question bank
|
And I choose "Edit question" action for "Test question to be previewed" in the question bank
|
||||||
And I set the field "Question name" to "New version"
|
And I set the field "Question name" to "New version"
|
||||||
And I set the field "Question text" to "New text version"
|
And I set the field "Question text" to "New text version"
|
||||||
And I click on "submitbutton" "button"
|
And I click on "submitbutton" "button"
|
||||||
And I choose "Preview" action for "New version" in the question bank
|
And I choose "Preview" action for "New version" in the question bank
|
||||||
Then I should see "Version 2"
|
When I expand all fieldsets
|
||||||
|
And I should see "Version 2"
|
||||||
And I should see "(latest)"
|
And I should see "(latest)"
|
||||||
And I should see "New version"
|
And I should see "New version"
|
||||||
And I should see "New text version"
|
And I should see "New text version"
|
||||||
And I should not see "Test question to be previewed"
|
And I should not see "Test question to be previewed"
|
||||||
And I should not see "Version 1"
|
And I should not see "Version 1"
|
||||||
|
And I should see "1" in the "Question version" "select"
|
||||||
|
And I should see "2" in the "Question version" "select"
|
||||||
|
And I set the field "Question version" to "1"
|
||||||
|
And I press "Start again with these options"
|
||||||
|
Then I should see "Version 1"
|
||||||
|
And I should not see "Version 2"
|
||||||
|
And I should not see "(latest)"
|
||||||
|
|
||||||
|
Scenario: The preview always uses the latest question version by default.
|
||||||
|
Given the following "core_question > updated questions" exist:
|
||||||
|
| questioncategory | question | questiontext |
|
||||||
|
| Test questions | Test question to be previewed | Question version 2 |
|
||||||
|
And I should see "Version 1 (latest)"
|
||||||
|
And I expand all fieldsets
|
||||||
|
And the field "Question version" matches value "Always latest"
|
||||||
|
And I set the field "Answer:" to "3.14"
|
||||||
|
And I press "Submit and finish"
|
||||||
|
And I should see "Version 1"
|
||||||
|
When I press "Start again"
|
||||||
|
Then I should not see "Version 1"
|
||||||
|
And I should see "Version 2 (latest)"
|
||||||
|
|
||||||
|
Scenario: Detect a newer version during always latest preview and offer to switch to the latest
|
||||||
|
Given I should not see "This preview is using version 1"
|
||||||
|
And the following "core_question > updated questions" exist:
|
||||||
|
| questioncategory | question | questiontext |
|
||||||
|
| Test questions | Test question to be previewed | Question version 2 |
|
||||||
|
And I should see "Version 1 (latest)"
|
||||||
|
And I set the field "Answer:" to "3.14"
|
||||||
|
When I press "Submit and finish"
|
||||||
|
And I should see "This preview is using version 1 of this question. The latest version is 2."
|
||||||
|
And I press "Restart now"
|
||||||
|
Then I should not see "Version 1"
|
||||||
|
And I should see "Version 2 (latest)"
|
||||||
|
|
||||||
|
Scenario: Previewing from the question history will not always show the latest version
|
||||||
|
Given I press "Close preview"
|
||||||
|
And the following "core_question > updated questions" exist:
|
||||||
|
| questioncategory | question | questiontext |
|
||||||
|
| Test questions | Test question to be previewed | Question version 2 |
|
||||||
|
And I choose "History" action for "Test question to be previewed" in the question bank
|
||||||
|
And I choose "Preview" action for "Test question to be previewed" in the question bank
|
||||||
|
And I should see "Version 1"
|
||||||
|
And I expand all fieldsets
|
||||||
|
And the field "Question version" matches value "1"
|
||||||
|
And I set the field "Answer:" to "3.14"
|
||||||
|
And I press "Submit and finish"
|
||||||
|
And I should see "Version 1"
|
||||||
|
And I should not see "The latest version is 2."
|
||||||
|
And the following "core_question > updated questions" exist:
|
||||||
|
| questioncategory | question | questiontext |
|
||||||
|
| Test questions | Test question to be previewed | Question version 3 |
|
||||||
|
When I press "Start again"
|
||||||
|
Then I should see "Version 1"
|
||||||
|
And I should not see "Version 3 (latest)"
|
||||||
|
|
||||||
Scenario: Question preview can be closed
|
Scenario: Question preview can be closed
|
||||||
And I press "Close preview"
|
And I press "Close preview"
|
||||||
|
@ -92,6 +92,26 @@ class qbank_preview_helper_test extends \advanced_testcase {
|
|||||||
* @covers ::question_preview_action_url
|
* @covers ::question_preview_action_url
|
||||||
*/
|
*/
|
||||||
public function test_question_preview_action_url() {
|
public function test_question_preview_action_url() {
|
||||||
|
$actionurl = helper::question_preview_action_url($this->questiondata->id, $this->quba->get_id(), $this->options,
|
||||||
|
$this->context, $this->returnurl, question_preview_options::ALWAYS_LATEST);
|
||||||
|
$params = [
|
||||||
|
'id' => $this->questiondata->id,
|
||||||
|
'previewid' => $this->quba->get_id(),
|
||||||
|
'returnurl' => $this->returnurl,
|
||||||
|
'courseid' => $this->context->instanceid,
|
||||||
|
'restartversion' => question_preview_options::ALWAYS_LATEST,
|
||||||
|
];
|
||||||
|
$params = array_merge($params, $this->options->get_url_params());
|
||||||
|
$expectedurl = new moodle_url('/question/bank/previewquestion/preview.php', $params);
|
||||||
|
$this->assertEquals($expectedurl, $actionurl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the preview action url from the helper class when no restartversion is passed.
|
||||||
|
*
|
||||||
|
* @covers ::question_preview_action_url
|
||||||
|
*/
|
||||||
|
public function test_question_preview_action_url_no_restartversion() {
|
||||||
$actionurl = helper::question_preview_action_url($this->questiondata->id, $this->quba->get_id(), $this->options,
|
$actionurl = helper::question_preview_action_url($this->questiondata->id, $this->quba->get_id(), $this->options,
|
||||||
$this->context, $this->returnurl);
|
$this->context, $this->returnurl);
|
||||||
$params = [
|
$params = [
|
||||||
@ -111,7 +131,8 @@ class qbank_preview_helper_test extends \advanced_testcase {
|
|||||||
* @covers ::question_preview_form_url
|
* @covers ::question_preview_form_url
|
||||||
*/
|
*/
|
||||||
public function test_question_preview_form_url() {
|
public function test_question_preview_form_url() {
|
||||||
$formurl = helper::question_preview_form_url($this->questiondata->id, $this->context, $this->quba->get_id(), $this->returnurl);
|
$formurl = helper::question_preview_form_url(
|
||||||
|
$this->questiondata->id, $this->context, $this->quba->get_id(), $this->returnurl);
|
||||||
$params = [
|
$params = [
|
||||||
'id' => $this->questiondata->id,
|
'id' => $this->questiondata->id,
|
||||||
'previewid' => $this->quba->get_id(),
|
'previewid' => $this->quba->get_id(),
|
||||||
@ -129,12 +150,40 @@ class qbank_preview_helper_test extends \advanced_testcase {
|
|||||||
*/
|
*/
|
||||||
public function test_question_preview_url() {
|
public function test_question_preview_url() {
|
||||||
$previewurl = helper::question_preview_url($this->questiondata->id, $this->options->behaviour, $this->options->maxmark,
|
$previewurl = helper::question_preview_url($this->questiondata->id, $this->options->behaviour, $this->options->maxmark,
|
||||||
$this->options, $this->options->variant, $this->context);
|
$this->options, $this->options->variant, $this->context, null, question_preview_options::ALWAYS_LATEST);
|
||||||
$params = [
|
$params = [
|
||||||
'id' => $this->questiondata->id,
|
'id' => $this->questiondata->id,
|
||||||
'behaviour' => $this->options->behaviour,
|
'behaviour' => $this->options->behaviour,
|
||||||
'maxmark' => $this->options->maxmark,
|
'maxmark' => $this->options->maxmark,
|
||||||
'courseid' => $this->context->instanceid
|
'courseid' => $this->context->instanceid,
|
||||||
|
'restartversion' => question_preview_options::ALWAYS_LATEST,
|
||||||
|
];
|
||||||
|
// Extra params for options.
|
||||||
|
$params['correctness'] = $this->options->correctness;
|
||||||
|
$params['marks'] = $this->options->marks;
|
||||||
|
$params['markdp'] = $this->options->markdp;
|
||||||
|
$params['feedback'] = (bool) $this->options->feedback;
|
||||||
|
$params['generalfeedback'] = (bool) $this->options->generalfeedback;
|
||||||
|
$params['rightanswer'] = (bool) $this->options->rightanswer;
|
||||||
|
$params['history'] = (bool) $this->options->history;
|
||||||
|
$expectedurl = new moodle_url('/question/bank/previewquestion/preview.php', $params);
|
||||||
|
$this->assertEquals($expectedurl, $previewurl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the preview url from the helper class.
|
||||||
|
*
|
||||||
|
* @covers ::question_preview_url
|
||||||
|
*/
|
||||||
|
public function test_question_preview_url_no_restartversion() {
|
||||||
|
$previewurl = helper::question_preview_url($this->questiondata->id, $this->options->behaviour, $this->options->maxmark,
|
||||||
|
$this->options, $this->options->variant, $this->context, null);
|
||||||
|
$params = [
|
||||||
|
'id' => $this->questiondata->id,
|
||||||
|
'behaviour' => $this->options->behaviour,
|
||||||
|
'maxmark' => $this->options->maxmark,
|
||||||
|
'courseid' => $this->context->instanceid,
|
||||||
];
|
];
|
||||||
// Extra params for options.
|
// Extra params for options.
|
||||||
$params['correctness'] = $this->options->correctness;
|
$params['correctness'] = $this->options->correctness;
|
||||||
@ -188,4 +237,28 @@ class qbank_preview_helper_test extends \advanced_testcase {
|
|||||||
$versionids = helper::load_versions($question->questionbankentryid);
|
$versionids = helper::load_versions($question->questionbankentryid);
|
||||||
$this->assertCount(2, $versionids);
|
$this->assertCount(2, $versionids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method get_restart_id().
|
||||||
|
*
|
||||||
|
* This should return the value of the specified version number, or the latest version if ALWAYS_LATEST is passed.
|
||||||
|
*
|
||||||
|
* @covers ::get_restart_id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function test_get_restart_id(): void {
|
||||||
|
$versions = [
|
||||||
|
100 => 1,
|
||||||
|
200 => 2,
|
||||||
|
300 => 3
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertEquals(100, helper::get_restart_id($versions, 1));
|
||||||
|
$this->assertEquals(200, helper::get_restart_id($versions, 2));
|
||||||
|
$this->assertEquals(300, helper::get_restart_id($versions, 3));
|
||||||
|
$this->assertEquals(300, helper::get_restart_id($versions, question_preview_options::ALWAYS_LATEST));
|
||||||
|
$this->assertNull(helper::get_restart_id($versions, 4));
|
||||||
|
$this->assertNull(helper::get_restart_id([], 1));
|
||||||
|
$this->assertNull(helper::get_restart_id([], question_preview_options::ALWAYS_LATEST));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1257,4 +1257,13 @@ class view {
|
|||||||
public function get_visiblecolumns(): array {
|
public function get_visiblecolumns(): array {
|
||||||
return $this->visiblecolumns;
|
return $this->visiblecolumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this view showing separate versions of a question?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_listing_specific_versions(): bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,12 @@ class behat_core_question_generator extends behat_generator_base {
|
|||||||
'required' => ['question', 'tag'],
|
'required' => ['question', 'tag'],
|
||||||
'switchids' => ['question' => 'questionid'],
|
'switchids' => ['question' => 'questionid'],
|
||||||
],
|
],
|
||||||
|
'updated questions' => [
|
||||||
|
'singular' => 'question',
|
||||||
|
'datagenerator' => 'updated_question',
|
||||||
|
'required' => ['question', 'questioncategory'],
|
||||||
|
'switchids' => ['question' => 'id', 'questioncategory' => 'category'],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +64,22 @@ class behat_core_question_generator extends behat_generator_base {
|
|||||||
}
|
}
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a question
|
||||||
|
*
|
||||||
|
* This will update a question matching the supplied name with the provided data, creating a new version in the process.
|
||||||
|
*
|
||||||
|
* @param array $data the row of data from the behat script.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function process_updated_question(array $data): void {
|
||||||
|
global $DB;
|
||||||
|
$question = $DB->get_record('question', ['id' => $data['id']], '*', MUST_EXIST);
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$question->{$key} = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->datagenerator->get_plugin_generator('core_question')->update_question($question);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user