mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
Merge branch 'MDL-77745_master' of https://github.com/marxjohnson/moodle
This commit is contained in:
commit
094f5dbb5b
@ -463,6 +463,8 @@ $string['rightanswer'] = 'Right answer';
|
|||||||
$string['rightanswer_help'] = 'An automatically generated summary of the correct response. This can be limited, so you may wish to consider explaining the correct solution in the general feedback for the question, and turning this option off.';
|
$string['rightanswer_help'] = 'An automatically generated summary of the correct response. This can be limited, so you may wish to consider explaining the correct solution in the general feedback for the question, and turning this option off.';
|
||||||
$string['saved'] = 'Saved: {$a}';
|
$string['saved'] = 'Saved: {$a}';
|
||||||
$string['settingsformultipletries'] = 'Multiple tries';
|
$string['settingsformultipletries'] = 'Multiple tries';
|
||||||
|
$string['shortversioninfo'] = 'v{$a->version} (of {$a->latestversion})';
|
||||||
|
$string['shortversioninfolatest'] = 'v{$a->version} (latest)';
|
||||||
$string['showhidden'] = 'Also show old questions';
|
$string['showhidden'] = 'Also show old questions';
|
||||||
$string['showmarkandmax'] = 'Show mark and max';
|
$string['showmarkandmax'] = 'Show mark and max';
|
||||||
$string['showmaxmarkonly'] = 'Show max mark only';
|
$string['showmaxmarkonly'] = 'Show max mark only';
|
||||||
@ -511,6 +513,8 @@ $string['qbanknotfound'] = 'The \'{$a}\' question bank plugin doesn\'t exist or
|
|||||||
$string['noquestionbanks'] = 'No question bank plugin found.';
|
$string['noquestionbanks'] = 'No question bank plugin found.';
|
||||||
$string['questionloaderror'] = 'Could not load the question options.';
|
$string['questionloaderror'] = 'Could not load the question options.';
|
||||||
$string['version_selection'] = 'Version {$a->version}';
|
$string['version_selection'] = 'Version {$a->version}';
|
||||||
|
$string['versioninfo'] = 'Version {$a->version} (of {$a->latestversion})';
|
||||||
|
$string['versioninfolatest'] = 'Version {$a->version} (latest)';
|
||||||
$string['question_version'] = 'Question version';
|
$string['question_version'] = 'Question version';
|
||||||
|
|
||||||
// Deprecated since Moodle 4.0.
|
// Deprecated since Moodle 4.0.
|
||||||
|
@ -32,6 +32,7 @@ Feature: The various checks that may happen when an attept is started
|
|||||||
When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student"
|
When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student"
|
||||||
And I press "Attempt quiz"
|
And I press "Attempt quiz"
|
||||||
Then I should see "Text of the first question"
|
Then I should see "Text of the first question"
|
||||||
|
And I should not see "v1" in the "Question 1" "question"
|
||||||
|
|
||||||
@javascript
|
@javascript
|
||||||
Scenario: Start a quiz with time limit and password
|
Scenario: Start a quiz with time limit and password
|
||||||
|
@ -12,8 +12,8 @@ Feature: Preview a quiz as a teacher
|
|||||||
| fullname | shortname | category |
|
| fullname | shortname | category |
|
||||||
| Course 1 | C1 | 0 |
|
| Course 1 | C1 | 0 |
|
||||||
And the following "course enrolments" exist:
|
And the following "course enrolments" exist:
|
||||||
| user | course | role |
|
| user | course | role |
|
||||||
| teacher | C1 | teacher |
|
| teacher | C1 | editingteacher |
|
||||||
And the following "question categories" exist:
|
And the following "question categories" exist:
|
||||||
| contextlevel | reference | name |
|
| contextlevel | reference | name |
|
||||||
| Course | C1 | Test questions |
|
| Course | C1 | Test questions |
|
||||||
@ -38,6 +38,7 @@ Feature: Preview a quiz as a teacher
|
|||||||
When I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher"
|
When I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher"
|
||||||
And I follow "Review"
|
And I follow "Review"
|
||||||
Then I should see "25.00 out of 100.00"
|
Then I should see "25.00 out of 100.00"
|
||||||
|
And I should see "v1 (latest)" in the "Question 1" "question"
|
||||||
And I follow "Finish review"
|
And I follow "Finish review"
|
||||||
And "Review" "link" in the "Preview" "table_row" should be visible
|
And "Review" "link" in the "Preview" "table_row" should be visible
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ Feature: Preview a quiz as a teacher
|
|||||||
Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher"
|
Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher"
|
||||||
When I press "Preview quiz"
|
When I press "Preview quiz"
|
||||||
Then I should see "Question 1"
|
Then I should see "Question 1"
|
||||||
|
And I should see "v1 (latest)" in the "Question 1" "question"
|
||||||
And "Start a new preview" "button" should exist
|
And "Start a new preview" "button" should exist
|
||||||
|
|
||||||
Scenario: Teachers should see a notice if the quiz is not available to students
|
Scenario: Teachers should see a notice if the quiz is not available to students
|
||||||
|
@ -83,6 +83,7 @@ $maxvariant = min($question->get_num_variants(), QUESTION_PREVIEW_MAX_VARIANTS);
|
|||||||
$options = new question_preview_options($question);
|
$options = new question_preview_options($question);
|
||||||
$options->load_user_defaults();
|
$options->load_user_defaults();
|
||||||
$options->set_from_request();
|
$options->set_from_request();
|
||||||
|
$options->versioninfo = false;
|
||||||
$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, null, $restartversion));
|
$options, $options->variant, $context, null, $restartversion));
|
||||||
|
|
||||||
@ -264,11 +265,9 @@ $previewdata = [];
|
|||||||
$previewdata['questionicon'] = print_question_icon($question);
|
$previewdata['questionicon'] = print_question_icon($question);
|
||||||
$previewdata['questionidumber'] = $question->idnumber;
|
$previewdata['questionidumber'] = $question->idnumber;
|
||||||
$previewdata['questiontitle'] = $question->name;
|
$previewdata['questiontitle'] = $question->name;
|
||||||
$islatestversion = is_latest($question->version, $question->questionbankentryid);
|
$versioninfo = new \core_question\output\question_version_info($question);
|
||||||
if ($islatestversion) {
|
$previewdata['versiontitle'] = $versioninfo->export_for_template($OUTPUT);
|
||||||
$previewdata['versiontitle'] = get_string('versiontitlelatest', 'qbank_previewquestion', $question->version);
|
if ($versioninfo->version !== $versioninfo->latestversion) {
|
||||||
} else {
|
|
||||||
$previewdata['versiontitle'] = get_string('versiontitle', 'qbank_previewquestion', $question->version);
|
|
||||||
if ($restartversion == question_preview_options::ALWAYS_LATEST) {
|
if ($restartversion == question_preview_options::ALWAYS_LATEST) {
|
||||||
$newerversionparams = (object) [
|
$newerversionparams = (object) [
|
||||||
'currentversion' => $question->version,
|
'currentversion' => $question->version,
|
||||||
|
@ -41,7 +41,9 @@
|
|||||||
"question": "<div>question html</div>",
|
"question": "<div>question html</div>",
|
||||||
"questionicon": "<i class='icon fa fa-search-plus fa-fw' title='Preview question' aria-label='Preview question'></i>",
|
"questionicon": "<i class='icon fa fa-search-plus fa-fw' title='Preview question' aria-label='Preview question'></i>",
|
||||||
"questiontitle": "Question title",
|
"questiontitle": "Question title",
|
||||||
"versiontitle": "Version 3 (latest)",
|
"versiontitle": {
|
||||||
|
"versioninfo": "Version 3 (latest)"
|
||||||
|
},
|
||||||
"questionidumber": "qidnumber1",
|
"questionidumber": "qidnumber1",
|
||||||
"restartdisabled": "disabled='disabled'",
|
"restartdisabled": "disabled='disabled'",
|
||||||
"finishdisabled": "disabled='disabled'",
|
"finishdisabled": "disabled='disabled'",
|
||||||
@ -58,7 +60,9 @@
|
|||||||
<h2 class="mt-2">{{{questionicon}}}</h2>
|
<h2 class="mt-2">{{{questionicon}}}</h2>
|
||||||
<h2 class="ml-2 mt-2"> {{questiontitle}}</h2>
|
<h2 class="ml-2 mt-2"> {{questiontitle}}</h2>
|
||||||
<h3 class="px-2 py-1 ml-2 mt-2">
|
<h3 class="px-2 py-1 ml-2 mt-2">
|
||||||
<span class="badge bg-primary text-light">{{versiontitle}}</span>
|
{{#versiontitle}}
|
||||||
|
{{>core_question/question_version_info}}
|
||||||
|
{{/versiontitle}}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
{{#newerversion}}
|
{{#newerversion}}
|
||||||
|
@ -149,18 +149,18 @@ Feature: A teacher can preview questions in the question bank
|
|||||||
| Test questions | Test question to be previewed | Question version 2 |
|
| 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 "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 choose "Preview" action for "Test question to be previewed" in the question bank
|
||||||
And I should see "Version 1"
|
And I should see "Version 1 (of 2)"
|
||||||
And I expand all fieldsets
|
And I expand all fieldsets
|
||||||
And the field "Question version" matches value "1"
|
And the field "Question version" matches value "1"
|
||||||
And I set the field "Answer:" to "3.14"
|
And I set the field "Answer:" to "3.14"
|
||||||
And I press "Submit and finish"
|
And I press "Submit and finish"
|
||||||
And I should see "Version 1"
|
And I should see "Version 1 (of 2)"
|
||||||
And I should not see "The latest version is 2."
|
And I should not see "The latest version is 2."
|
||||||
And the following "core_question > updated questions" exist:
|
And the following "core_question > updated questions" exist:
|
||||||
| questioncategory | question | questiontext |
|
| questioncategory | question | questiontext |
|
||||||
| Test questions | Test question to be previewed | Question version 3 |
|
| Test questions | Test question to be previewed | Question version 3 |
|
||||||
When I press "Start again"
|
When I press "Start again"
|
||||||
Then I should see "Version 1"
|
Then I should see "Version 1 (of 3)"
|
||||||
And I should not see "Version 3 (latest)"
|
And I should not see "Version 3 (latest)"
|
||||||
|
|
||||||
Scenario: Question preview can be closed
|
Scenario: Question preview can be closed
|
||||||
|
@ -36,6 +36,7 @@ Feature: Use the qbank plugin manager page for question usage
|
|||||||
And I should see "0" on the usage column
|
And I should see "0" on the usage column
|
||||||
When I click "0" on the usage column
|
When I click "0" on the usage column
|
||||||
Then I should see "Version 1"
|
Then I should see "Version 1"
|
||||||
|
And I should see "v1 (latest)" in the "Question 1" "question"
|
||||||
And I click on "Close" "button" in the ".modal-dialog" "css_element"
|
And I click on "Close" "button" in the ".modal-dialog" "css_element"
|
||||||
And I should see "0" on the usage column
|
And I should see "0" on the usage column
|
||||||
|
|
||||||
|
115
question/classes/output/question_version_info.php
Normal file
115
question/classes/output/question_version_info.php
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?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/>.
|
||||||
|
|
||||||
|
namespace core_question\output;
|
||||||
|
|
||||||
|
use renderer_base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track and display question version information.
|
||||||
|
*
|
||||||
|
* This class handles rendering the question version information (the current version of the question, the total number of versions,
|
||||||
|
* and if the current version is the latest). It also tracks loaded question definitions that don't yet have the latest version
|
||||||
|
* loaded, and handles loading the latest version of all pending questions.
|
||||||
|
*
|
||||||
|
* @package core_question
|
||||||
|
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||||
|
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
class question_version_info implements \renderable, \templatable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array List of definitions that don't know whether they are the latest version yet.
|
||||||
|
*/
|
||||||
|
public static array $pendingdefinitions = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int $version The current version number.
|
||||||
|
*/
|
||||||
|
public int $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ?int $latestversion The latest version number of this question.
|
||||||
|
*/
|
||||||
|
public ?int $latestversion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool $shortversion Are we displaying an abbreviation for "version" rather than the full word?
|
||||||
|
*/
|
||||||
|
protected bool $shortversion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the current and latest versions of the question, and whether we want to abbreviate the output string.
|
||||||
|
*
|
||||||
|
* @param \question_definition $question
|
||||||
|
* @param bool $shortversion
|
||||||
|
*/
|
||||||
|
public function __construct(\question_definition $question, bool $shortversion = false) {
|
||||||
|
$this->version = $question->version;
|
||||||
|
$this->latestversion = $question->latestversion;
|
||||||
|
$this->shortversion = $shortversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and set the latest version of all pending question_definition objects.
|
||||||
|
*
|
||||||
|
* This will update all pending objects in one go, saving us having to do a query for each question.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function populate_latest_versions(): void {
|
||||||
|
global $DB;
|
||||||
|
$pendingentryids = array_map(fn($definition) => $definition->questionbankentryid, self::$pendingdefinitions);
|
||||||
|
[$insql, $params] = $DB->get_in_or_equal($pendingentryids);
|
||||||
|
|
||||||
|
$sql = "SELECT questionbankentryid, MAX(version) AS latestversion
|
||||||
|
FROM {question_versions}
|
||||||
|
WHERE questionbankentryid $insql
|
||||||
|
GROUP BY questionbankentryid";
|
||||||
|
$latestversions = $DB->get_records_sql_menu($sql, $params);
|
||||||
|
array_walk(self::$pendingdefinitions, function($definition) use ($latestversions) {
|
||||||
|
if (!isset($latestversions[$definition->questionbankentryid])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$definition->set_latest_version($latestversions[$definition->questionbankentryid]);
|
||||||
|
unset(self::$pendingdefinitions[$definition->id]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the question version info as a string, including the version number and whether this is the latest version.
|
||||||
|
*
|
||||||
|
* @param renderer_base $output
|
||||||
|
* @return array
|
||||||
|
* @throws \coding_exception
|
||||||
|
*/
|
||||||
|
public function export_for_template(renderer_base $output): array {
|
||||||
|
if (is_null($this->latestversion)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$identifier = 'versioninfo';
|
||||||
|
if ($this->version === $this->latestversion) {
|
||||||
|
$identifier .= 'latest';
|
||||||
|
}
|
||||||
|
if ($this->shortversion) {
|
||||||
|
$identifier = 'short' . $identifier;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'versioninfo' => get_string($identifier, 'question', $this)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,7 @@
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use core_question\output\question_version_info;
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
@ -285,7 +286,9 @@ abstract class question_bank {
|
|||||||
* @return question_definition loaded from the database.
|
* @return question_definition loaded from the database.
|
||||||
*/
|
*/
|
||||||
public static function make_question($questiondata) {
|
public static function make_question($questiondata) {
|
||||||
return self::get_qtype($questiondata->qtype, false)->make_question($questiondata, false);
|
$definition = self::get_qtype($questiondata->qtype, false)->make_question($questiondata, false);
|
||||||
|
question_version_info::$pendingdefinitions[$definition->id] = $definition;
|
||||||
|
return $definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -653,6 +653,11 @@ class question_display_options {
|
|||||||
*/
|
*/
|
||||||
public $questionidentifier = null;
|
public $questionidentifier = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ?bool $versioninfo Should we display the version in the question info?
|
||||||
|
*/
|
||||||
|
public ?bool $versioninfo = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set all the feedback-related fields {@link $feedback}, {@link generalfeedback},
|
* Set all the feedback-related fields {@link $feedback}, {@link generalfeedback},
|
||||||
* {@link rightanswer} and {@link manualcomment} to
|
* {@link rightanswer} and {@link manualcomment} to
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use core_question\local\bank\question_edit_contexts;
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
@ -903,6 +904,9 @@ class question_attempt {
|
|||||||
global $PAGE;
|
global $PAGE;
|
||||||
$page = $PAGE;
|
$page = $PAGE;
|
||||||
}
|
}
|
||||||
|
if (is_null($options->versioninfo)) {
|
||||||
|
$options->versioninfo = (new question_edit_contexts($page->context))->have_one_edit_tab_cap('questions');
|
||||||
|
}
|
||||||
$qoutput = $page->get_renderer('core', 'question');
|
$qoutput = $page->get_renderer('core', 'question');
|
||||||
$qtoutput = $this->question->get_renderer($page);
|
$qtoutput = $this->question->get_renderer($page);
|
||||||
return $this->behaviour->render($options, $number, $qoutput, $qtoutput);
|
return $this->behaviour->render($options, $number, $qoutput, $qtoutput);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use core_question\output\question_version_info;
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
@ -145,6 +146,9 @@ class core_question_renderer extends plugin_renderer_base {
|
|||||||
$output .= $this->mark_summary($qa, $behaviouroutput, $options);
|
$output .= $this->mark_summary($qa, $behaviouroutput, $options);
|
||||||
$output .= $this->question_flag($qa, $options->flags);
|
$output .= $this->question_flag($qa, $options->flags);
|
||||||
$output .= $this->edit_question_link($qa, $options);
|
$output .= $this->edit_question_link($qa, $options);
|
||||||
|
if ($options->versioninfo) {
|
||||||
|
$output .= $this->render(new question_version_info($qa->get_question(), true));
|
||||||
|
}
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
question/templates/question_version_info.mustache
Normal file
26
question/templates/question_version_info.mustache
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{{!
|
||||||
|
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 core_question/question_version_info
|
||||||
|
|
||||||
|
Displays a badge containing the version information of a question
|
||||||
|
* versioninfo - The version information string, including the number and whether it is the latest verision.
|
||||||
|
|
||||||
|
Example context (json):
|
||||||
|
{
|
||||||
|
"versioninfo": "Version 2 (latest)"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
<span class="badge bg-primary text-light">{{versioninfo}}</span>
|
@ -17,6 +17,7 @@
|
|||||||
namespace core_question;
|
namespace core_question;
|
||||||
|
|
||||||
use core_question\local\bank\question_version_status;
|
use core_question\local\bank\question_version_status;
|
||||||
|
use core_question\output\question_version_info;
|
||||||
use question_bank;
|
use question_bank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,6 +66,11 @@ class version_test extends \advanced_testcase {
|
|||||||
$this->context = \context_module::instance($this->quiz->cmid);
|
$this->context = \context_module::instance($this->quiz->cmid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void {
|
||||||
|
question_version_info::$pendingdefinitions = [];
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if creating a question a new version and bank entry records are created.
|
* Test if creating a question a new version and bank entry records are created.
|
||||||
*
|
*
|
||||||
@ -320,4 +326,48 @@ class version_test extends \advanced_testcase {
|
|||||||
$this->assertEquals($questionbankentryid->questionbankentryid, $questionbankentryids);
|
$this->assertEquals($questionbankentryid->questionbankentryid, $questionbankentryids);
|
||||||
$this->assertEquals($questionversions, $questionversionsofquestions[$questionbankentryids]);
|
$this->assertEquals($questionversions, $questionversionsofquestions[$questionbankentryids]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test population of latestversion field in question_definition objects
|
||||||
|
*
|
||||||
|
* When an instance of question_definition is created, it is added to an array of pending definitions which
|
||||||
|
* do not yet have the latestversion field populated. When one definition has its latestversion property accessed,
|
||||||
|
* all pending definitions have their latestversion field populated at once.
|
||||||
|
*
|
||||||
|
* @covers \core_question\output\question_version_info::populate_latest_versions()
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function test_populate_definition_latestversions() {
|
||||||
|
$qcategory = $this->qgenerator->create_question_category(['contextid' => $this->context->id]);
|
||||||
|
$question1 = $this->qgenerator->create_question('shortanswer', null, ['category' => $qcategory->id]);
|
||||||
|
$question2 = $this->qgenerator->create_question('shortanswer', null, ['category' => $qcategory->id]);
|
||||||
|
$question3 = $this->qgenerator->update_question($question2, null, ['idnumber' => 'id2']);
|
||||||
|
|
||||||
|
$latestversioninspector = new \ReflectionProperty('question_definition', 'latestversion');
|
||||||
|
$latestversioninspector->setAccessible(true);
|
||||||
|
$this->assertEmpty(question_version_info::$pendingdefinitions);
|
||||||
|
|
||||||
|
$questiondef1 = question_bank::load_question($question1->id);
|
||||||
|
$questiondef2 = question_bank::load_question($question2->id);
|
||||||
|
$questiondef3 = question_bank::load_question($question3->id);
|
||||||
|
|
||||||
|
$this->assertContains($questiondef1, question_version_info::$pendingdefinitions);
|
||||||
|
$this->assertContains($questiondef2, question_version_info::$pendingdefinitions);
|
||||||
|
$this->assertContains($questiondef3, question_version_info::$pendingdefinitions);
|
||||||
|
$this->assertNull($latestversioninspector->getValue($questiondef1));
|
||||||
|
$this->assertNull($latestversioninspector->getValue($questiondef2));
|
||||||
|
$this->assertNull($latestversioninspector->getValue($questiondef3));
|
||||||
|
|
||||||
|
// Read latestversion from one definition. This should populate the field in all pending definitions.
|
||||||
|
$latestversion1 = $questiondef1->latestversion;
|
||||||
|
|
||||||
|
$this->assertEmpty(question_version_info::$pendingdefinitions);
|
||||||
|
$this->assertNotNull($latestversioninspector->getValue($questiondef1));
|
||||||
|
$this->assertNotNull($latestversioninspector->getValue($questiondef2));
|
||||||
|
$this->assertNotNull($latestversioninspector->getValue($questiondef3));
|
||||||
|
$this->assertEquals($latestversion1, $latestversioninspector->getValue($questiondef1));
|
||||||
|
$this->assertEquals($questiondef1->version, $questiondef1->latestversion);
|
||||||
|
$this->assertNotEquals($questiondef2->version, $questiondef2->latestversion);
|
||||||
|
$this->assertEquals($questiondef3->version, $questiondef3->latestversion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use core_question\output\question_version_info;
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
@ -130,6 +131,9 @@ abstract class question_definition {
|
|||||||
/** @var int Bank entry id for the question */
|
/** @var int Bank entry id for the question */
|
||||||
public $questionbankentryid;
|
public $questionbankentryid;
|
||||||
|
|
||||||
|
/** @var ?int The latest version of the question. null if we haven't checked yet. */
|
||||||
|
protected $latestversion = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array of array of \core_customfield\data_controller objects indexed by fieldid for the questions custom fields.
|
* @var array of array of \core_customfield\data_controller objects indexed by fieldid for the questions custom fields.
|
||||||
*/
|
*/
|
||||||
@ -143,6 +147,21 @@ abstract class question_definition {
|
|||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a pending definition tries to read its latest version, fill in the latest version for all pending definitions
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __get($name) {
|
||||||
|
if ($name === 'latestversion') {
|
||||||
|
if (isset(question_version_info::$pendingdefinitions[$this->id])) {
|
||||||
|
question_version_info::populate_latest_versions();
|
||||||
|
}
|
||||||
|
return $this->latestversion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string the name of the question type (for example multichoice) that this
|
* @return string the name of the question type (for example multichoice) that this
|
||||||
* question is.
|
* question is.
|
||||||
@ -512,6 +531,18 @@ abstract class question_definition {
|
|||||||
DEBUG_DEVELOPER);
|
DEBUG_DEVELOPER);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the latest version.
|
||||||
|
*
|
||||||
|
* Making $this->latestversion public would break the magic __get() behaviour above, so allow it to be set externally.
|
||||||
|
*
|
||||||
|
* @param int $latestversion
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set_latest_version(int $latestversion): void {
|
||||||
|
$this->latestversion = $latestversion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user