This commit is contained in:
Jun Pataleta 2021-03-31 21:26:39 +08:00
commit 9d35715453
15 changed files with 218 additions and 46 deletions

View File

@ -271,6 +271,10 @@ if ($mform->is_cancelled()) {
}
}
// If this is a new question, save defaults for user in user_preferences table.
if (empty($question->id)) {
$qtypeobj->save_defaults_for_new_questions($fromform);
}
$question = $qtypeobj->save_question($question, $fromform);
if (isset($fromform->tags)) {
// If we have any question context level tags then set those tags now.

View File

@ -20,15 +20,24 @@ Feature: Test creating a drag and drop into text question
@javascript
Scenario: Create a drag and drop into text question
When I add a "Drag and drop into text" question filling the form with:
| Question name | Drag and drop into text 001 |
| Question text | The [[1]] [[2]] on the [[3]]. |
| General feedback | The cat sat on the mat. |
| id_choices_0_answer | cat |
| id_choices_1_answer | sat |
| id_choices_2_answer | mat |
| id_choices_3_answer | dog |
| id_choices_4_answer | table |
| Hint 1 | First hint |
| Hint 2 | Second hint |
Then I should see "Drag and drop into text 001"
Given I add a "Drag and drop into text" question filling the form with:
| Question name | Drag and drop into text 001 |
| Question text | The [[1]] [[2]] on the [[3]]. |
| General feedback | The cat sat on the mat. |
| id_shuffleanswers | 1 |
| id_choices_0_answer | cat |
| id_choices_1_answer | sat |
| id_choices_2_answer | mat |
| id_choices_3_answer | dog |
| id_choices_4_answer | table |
| Penalty for each incorrect try | 20% |
| Hint 1 | First hint |
| Hint 2 | Second hint |
And I should see "Drag and drop into text 001"
# Checking that the next new question form displays user preferences settings.
When I press "Create a new question ..."
And I set the field "item_qtype_ddwtos" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
Then the following fields match these values:
| id_shuffleanswers | 1 |
| Penalty for each incorrect try | 20% |

View File

@ -113,6 +113,21 @@ abstract class question_edit_form extends question_wizard_form {
parent::__construct($submiturl, null, 'post', '', ['data-qtype' => $this->qtype()], $formeditable);
}
/**
* Return default value for a given form element either from user_preferences table or $default.
*
* To make use of user_preferences in your qtype default settings, you need to replace
* $mform->setDefault({elementname}, {defaultvalue}); in edit_{qtypename}_form.php with
* $mform->setDefault({elementname}, $this->get_default_value({elementname}, {defaultvalue}));
*
* @param string $name the name of the form field.
* @param mixed $default default value.
* @return string|null default value for a given form element.
*/
protected function get_default_value(string $name, $default): ?string {
return question_bank::get_qtype($this->qtype())->get_default_value($name, $default);
}
/**
* Build the form definition.
*
@ -121,10 +136,7 @@ abstract class question_edit_form extends question_wizard_form {
* override this method and remove the ones you don't want with $mform->removeElement().
*/
protected function definition() {
global $COURSE, $CFG, $DB, $PAGE;
$qtype = $this->qtype();
$langfile = "qtype_{$qtype}";
global $DB, $PAGE;
$mform = $this->_form;
@ -189,7 +201,7 @@ abstract class question_edit_form extends question_wizard_form {
$mform->addElement('float', 'defaultmark', get_string('defaultmark', 'question'),
array('size' => 7));
$mform->setDefault('defaultmark', 1);
$mform->setDefault('defaultmark', $this->get_default_value('defaultmark', 1));
$mform->addRule('defaultmark', null, 'required', null, 'client');
$mform->addElement('editor', 'generalfeedback', get_string('generalfeedback', 'question'),
@ -497,7 +509,7 @@ abstract class question_edit_form extends question_wizard_form {
$mform->addElement('select', 'penalty',
get_string('penaltyforeachincorrecttry', 'question'), $penaltyoptions);
$mform->addHelpButton('penalty', 'penaltyforeachincorrecttry', 'question');
$mform->setDefault('penalty', 0.3333333);
$mform->setDefault('penalty', $this->get_default_value('penalty', 0.3333333));
if (isset($this->question->hints)) {
$counthints = count($this->question->hints);

View File

@ -136,7 +136,7 @@ class qtype_gapselect_edit_form_base extends question_edit_form {
$mform->setExpanded('choicehdr', 1);
$mform->addElement('checkbox', 'shuffleanswers', get_string('shuffle', 'qtype_gapselect'));
$mform->setDefault('shuffleanswers', 0);
$mform->setDefault('shuffleanswers', $this->get_default_value('shuffleanswers', 0));
$textboxgroup = array();
$textboxgroup[] = $mform->createElement('group', 'choices',

View File

@ -319,6 +319,11 @@ abstract class qtype_gapselect_base extends question_type {
return $goupofanswers;
}
public function save_defaults_for_new_questions(stdClass $fromform): void {
parent::save_defaults_for_new_questions($fromform);
$this->set_default_value('shuffleanswers', $fromform->shuffleanswers ?? 0);
}
public function get_possible_responses($questiondata) {
$question = $this->make_question($questiondata);

View File

@ -0,0 +1,41 @@
@qtype @qtype_gapselect
Feature: Test creating a Select missing words question
As a teacher
In order to test my students
I need to be able to create Select missing words questions
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | T1 | Teacher1 | teacher1@moodle.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Question bank" in current page administration
@javascript
Scenario: Create a Select missing words question
Given I add a "Select missing words" question filling the form with:
| Question name | Select missing words 001 |
| Question text | The [[1]] [[2]] on the [[3]]. |
| General feedback | The cat sat on the mat. |
| id_shuffleanswers | 1 |
| id_choices_0_answer | cat |
| id_choices_1_answer | sat |
| id_choices_2_answer | mat |
| id_choices_3_answer | dog |
| id_choices_4_answer | table |
| Hint 1 | First hint |
| Hint 2 | Second hint |
And I should see "Select missing words 001"
# Checking that the next new question form displays user preferences settings.
When I press "Create a new question ..."
And I set the field "item_qtype_gapselect" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
Then the following fields match these values:
| id_shuffleanswers | 1 |

View File

@ -49,6 +49,10 @@ class qtype_gapselect_edit_form_base_testable extends qtype_gapselect_edit_form_
public function set_allowed_tags(array $allowed) {
$this->allowedhtmltags = $allowed;
}
public function qtype() {
return 'gapselect';
}
}

View File

@ -46,22 +46,25 @@ class qtype_multichoice_edit_form extends question_edit_form {
);
$mform->addElement('select', 'single',
get_string('answerhowmany', 'qtype_multichoice'), $menu);
$mform->setDefault('single', get_config('qtype_multichoice', 'answerhowmany'));
$mform->setDefault('single', $this->get_default_value('single',
get_config('qtype_multichoice', 'answerhowmany')));
$mform->addElement('advcheckbox', 'shuffleanswers',
get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0, 1));
$mform->addHelpButton('shuffleanswers', 'shuffleanswers', 'qtype_multichoice');
$mform->setDefault('shuffleanswers', get_config('qtype_multichoice', 'shuffleanswers'));
$mform->setDefault('shuffleanswers', $this->get_default_value('shuffleanswers',
get_config('qtype_multichoice', 'shuffleanswers')));
$mform->addElement('select', 'answernumbering',
get_string('answernumbering', 'qtype_multichoice'),
qtype_multichoice::get_numbering_styles());
$mform->setDefault('answernumbering', get_config('qtype_multichoice', 'answernumbering'));
$mform->setDefault('answernumbering', $this->get_default_value('answernumbering',
get_config('qtype_multichoice', 'answernumbering')));
$mform->addElement('selectyesno', 'showstandardinstruction',
get_string('showstandardinstruction', 'qtype_multichoice'), null, null, [0, 1]);
$mform->addHelpButton('showstandardinstruction', 'showstandardinstruction', 'qtype_multichoice');
$mform->setDefault('showstandardinstruction', 0);
$mform->setDefault('showstandardinstruction', $this->get_default_value('showstandardinstruction', 0));
$this->add_per_answer_fields($mform, get_string('choiceno', 'qtype_multichoice', '{no}'),
question_bank::fraction_options_full(), max(5, QUESTION_NUMANS_START));

View File

@ -85,6 +85,14 @@ class qtype_multichoice extends question_type {
return $options;
}
public function save_defaults_for_new_questions(stdClass $fromform): void {
parent::save_defaults_for_new_questions($fromform);
$this->set_default_value('single', $fromform->single);
$this->set_default_value('shuffleanswers', $fromform->shuffleanswers);
$this->set_default_value('answernumbering', $fromform->answernumbering);
$this->set_default_value('showstandardinstruction', $fromform->showstandardinstruction);
}
public function save_question_options($question) {
global $DB;
$context = $question->context;

View File

@ -38,22 +38,37 @@ Feature: Test creating a Multiple choice question
| Hint 2 | Second hint |
Then I should see "Multi-choice-001"
@javascript
Scenario: Create a Multiple choice question with single response
When I add a "Multiple choice" question filling the form with:
| Question name | Multi-choice-002 |
| Question text | Find the capital city of England. |
| General feedback | London is the capital city of England. |
| One or multiple answers? | One answer only |
| Choice 1 | Manchester |
| Choice 2 | Buckingham |
| Choice 3 | London |
| Choice 4 | Barcelona |
| Choice 5 | Paris |
| id_fraction_0 | None |
| id_fraction_1 | None |
| id_fraction_2 | 100% |
| id_fraction_3 | None |
| id_fraction_4 | None |
| Hint 1 | First hint |
| Hint 2 | Second hint |
Then I should see "Multi-choice-002"
Given I add a "Multiple choice" question filling the form with:
| Question name | Multi-choice-002 |
| Question text | Find the capital city of England. |
| General feedback | London is the capital city of England. |
| Default mark | 5 |
| One or multiple answers? | One answer only |
| Shuffle the choices? | 0 |
| Number the choices? | 1., 2., 3., ... |
| Show standard instructions | Yes |
| Choice 1 | Manchester |
| Choice 2 | Buckingham |
| Choice 3 | London |
| Choice 4 | Barcelona |
| Choice 5 | Paris |
| id_fraction_0 | None |
| id_fraction_1 | None |
| id_fraction_2 | 100% |
| id_fraction_3 | None |
| id_fraction_4 | None |
| Hint 1 | First hint |
| Hint 2 | Second hint |
And I should see "Multi-choice-002"
# Checking that the next new question form displays user preferences settings.
When I press "Create a new question ..."
And I set the field "Multiple choice" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
Then the following fields match these values:
| Default mark | 5 |
| One or multiple answers? | One answer only |
| Shuffle the choices? | 0 |
| Number the choices? | 1., 2., 3., ... |
| Show standard instructions | Yes |

View File

@ -295,6 +295,45 @@ class question_type {
public function set_default_options($questiondata) {
}
/**
* Return default value for a given form element either from user_preferences table or $default.
*
* @param string $name the name of the form element.
* @param mixed $default default value.
* @return string|null default value for a given form element.
*/
public function get_default_value(string $name, $default): ?string {
return get_user_preferences($this->plugin_name() . '_' . $name, $default ?? '0');
}
/**
* Save the default value for a given form element in user_preferences table.
*
* @param string $name the name of the value to set.
* @param string $value the setting value.
*/
public function set_default_value(string $name, string $value): void {
set_user_preference($this->plugin_name() . '_' . $name, $value);
}
/**
* Save question defaults when creating new questions.
*
* @param stdClass $fromform data from the form.
*/
public function save_defaults_for_new_questions(stdClass $fromform): void {
// Some question types may not make use of the certain form elements, so
// we need to do a check on the following generic form elements. For instance,
// 'defaultmark' is not use in qtype_multianswer and 'penalty' in not used in
// qtype_essay and qtype_recordrtc.
if (isset($fromform->defaultmark)) {
$this->set_default_value('defaultmark', $fromform->defaultmark);
}
if (isset($fromform->penalty)) {
$this->set_default_value('penalty', $fromform->penalty);
}
}
/**
* Saves (creates or updates) a question.
*

View File

@ -36,12 +36,13 @@ defined('MOODLE_INTERNAL') || die();
class qtype_shortanswer_edit_form extends question_edit_form {
protected function definition_inner($mform) {
$menu = array(
$menu = [
get_string('caseno', 'qtype_shortanswer'),
get_string('caseyes', 'qtype_shortanswer')
);
];
$mform->addElement('select', 'usecase',
get_string('casesensitive', 'qtype_shortanswer'), $menu);
$mform->setDefault('usecase', $this->get_default_value('usecase', $menu[0]));
$mform->addElement('static', 'answersinstruct',
get_string('correctanswers', 'qtype_shortanswer'),

View File

@ -54,6 +54,11 @@ class qtype_shortanswer extends question_type {
$this->delete_files_in_hints($questionid, $contextid);
}
public function save_defaults_for_new_questions(stdClass $fromform): void {
parent::save_defaults_for_new_questions($fromform);
$this->set_default_value('usecase', $fromform->usecase);
}
public function save_question_options($question) {
global $DB;
$result = new stdClass();

View File

@ -18,17 +18,24 @@ Feature: Test creating a Short answer question
And I am on "Course 1" course homepage
And I navigate to "Question bank" in current page administration
@javascript
Scenario: Create a Short answer question
When I add a "Short answer" question filling the form with:
Given I add a "Short answer" question filling the form with:
| Question name | shortanswer-001 |
| Question text | What is the national langauge in France? |
| General feedback | The national langauge in France is French |
| Default mark | 1 |
| Case sensitivity | No, case is unimportant |
| Case sensitivity | Yes, case must match |
| id_answer_0 | French |
| id_fraction_0 | 100% |
| id_feedback_0 | Well done. French is correct. |
| id_answer_1 | * |
| id_fraction_1 | None |
| id_feedback_1 | Your answer is incorrect. |
Then I should see "shortanswer-001"
And I should see "shortanswer-001"
# Checking that the next new question form displays user preferences settings.
When I press "Create a new question ..."
And I set the field "Short answer" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
Then the following fields match these values:
| Case sensitivity | Yes, case must match |

View File

@ -1,5 +1,24 @@
This files describes API changes for question type plugins.
=== 3.11 ===
* Introducing the following \question_type base class methods to save/fetch the last form values
that were used when creating questions as the new defaults when creating new questions:
- \question_type::get_default_value()
- Fetches the default value for a given question field from the user preference.
Question type plugins can use this in edit_{qtypename}_form.php when using $mform->setDefault().
- \question_type::set_default_value()
- Saves the default value for a given question form field in the user preferences.
- \question_type::save_defaults_for_new_questions()
- Saves the question type plugin's defined form defaults into the user preferences.
It calls \question_type::set_default_value() to save each form field default value
into the user preferences.
- Question type plugins using \question_type::get_default_value() for their form fields must implement
this in order to save the values from these form fields as defaults for new questions.
This will help teachers who repeatedly create questions and use the same values for the fields
(e.g. Default mark, Penalty for each incorrect try, etc.) in the question edit form.
=== 3.8 ===
* There is a new method for question types get_extra_question_bank_actions.