Commit 01403b2f authored by Mahmoud Kassaei's avatar Mahmoud Kassaei
Browse files

MDL-70895 Questions: Default options when creating a question

parent f0eb6a57
...@@ -271,6 +271,10 @@ if ($mform->is_cancelled()) { ...@@ -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); $question = $qtypeobj->save_question($question, $fromform);
if (isset($fromform->tags)) { if (isset($fromform->tags)) {
// If we have any question context level tags then set those tags now. // If we have any question context level tags then set those tags now.
......
...@@ -20,15 +20,24 @@ Feature: Test creating a drag and drop into text question ...@@ -20,15 +20,24 @@ Feature: Test creating a drag and drop into text question
@javascript @javascript
Scenario: Create a drag and drop into text question Scenario: Create a drag and drop into text question
When I add a "Drag and drop into text" question filling the form with: Given I add a "Drag and drop into text" question filling the form with:
| Question name | Drag and drop into text 001 | | Question name | Drag and drop into text 001 |
| Question text | The [[1]] [[2]] on the [[3]]. | | Question text | The [[1]] [[2]] on the [[3]]. |
| General feedback | The cat sat on the mat. | | General feedback | The cat sat on the mat. |
| id_shuffleanswers | 1 |
| id_choices_0_answer | cat | | id_choices_0_answer | cat |
| id_choices_1_answer | sat | | id_choices_1_answer | sat |
| id_choices_2_answer | mat | | id_choices_2_answer | mat |
| id_choices_3_answer | dog | | id_choices_3_answer | dog |
| id_choices_4_answer | table | | id_choices_4_answer | table |
| Penalty for each incorrect try | 20% |
| Hint 1 | First hint | | Hint 1 | First hint |
| Hint 2 | Second hint | | Hint 2 | Second hint |
Then I should see "Drag and drop into text 001" 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% |
...@@ -113,6 +113,21 @@ abstract class question_edit_form extends question_wizard_form { ...@@ -113,6 +113,21 @@ abstract class question_edit_form extends question_wizard_form {
parent::__construct($submiturl, null, 'post', '', ['data-qtype' => $this->qtype()], $formeditable); 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. * Build the form definition.
* *
...@@ -121,10 +136,7 @@ abstract class question_edit_form extends question_wizard_form { ...@@ -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(). * override this method and remove the ones you don't want with $mform->removeElement().
*/ */
protected function definition() { protected function definition() {
global $COURSE, $CFG, $DB, $PAGE; global $DB, $PAGE;
$qtype = $this->qtype();
$langfile = "qtype_{$qtype}";
$mform = $this->_form; $mform = $this->_form;
...@@ -189,7 +201,7 @@ abstract class question_edit_form extends question_wizard_form { ...@@ -189,7 +201,7 @@ abstract class question_edit_form extends question_wizard_form {
$mform->addElement('float', 'defaultmark', get_string('defaultmark', 'question'), $mform->addElement('float', 'defaultmark', get_string('defaultmark', 'question'),
array('size' => 7)); array('size' => 7));
$mform->setDefault('defaultmark', 1); $mform->setDefault('defaultmark', $this->get_default_value('defaultmark', 1));
$mform->addRule('defaultmark', null, 'required', null, 'client'); $mform->addRule('defaultmark', null, 'required', null, 'client');
$mform->addElement('editor', 'generalfeedback', get_string('generalfeedback', 'question'), $mform->addElement('editor', 'generalfeedback', get_string('generalfeedback', 'question'),
...@@ -497,7 +509,7 @@ abstract class question_edit_form extends question_wizard_form { ...@@ -497,7 +509,7 @@ abstract class question_edit_form extends question_wizard_form {
$mform->addElement('select', 'penalty', $mform->addElement('select', 'penalty',
get_string('penaltyforeachincorrecttry', 'question'), $penaltyoptions); get_string('penaltyforeachincorrecttry', 'question'), $penaltyoptions);
$mform->addHelpButton('penalty', 'penaltyforeachincorrecttry', 'question'); $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)) { if (isset($this->question->hints)) {
$counthints = count($this->question->hints); $counthints = count($this->question->hints);
......
...@@ -136,7 +136,7 @@ class qtype_gapselect_edit_form_base extends question_edit_form { ...@@ -136,7 +136,7 @@ class qtype_gapselect_edit_form_base extends question_edit_form {
$mform->setExpanded('choicehdr', 1); $mform->setExpanded('choicehdr', 1);
$mform->addElement('checkbox', 'shuffleanswers', get_string('shuffle', 'qtype_gapselect')); $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 = array();
$textboxgroup[] = $mform->createElement('group', 'choices', $textboxgroup[] = $mform->createElement('group', 'choices',
......
...@@ -319,6 +319,11 @@ abstract class qtype_gapselect_base extends question_type { ...@@ -319,6 +319,11 @@ abstract class qtype_gapselect_base extends question_type {
return $goupofanswers; 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) { public function get_possible_responses($questiondata) {
$question = $this->make_question($questiondata); $question = $this->make_question($questiondata);
......
@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 |
...@@ -49,6 +49,10 @@ class qtype_gapselect_edit_form_base_testable extends qtype_gapselect_edit_form_ ...@@ -49,6 +49,10 @@ class qtype_gapselect_edit_form_base_testable extends qtype_gapselect_edit_form_
public function set_allowed_tags(array $allowed) { public function set_allowed_tags(array $allowed) {
$this->allowedhtmltags = $allowed; $this->allowedhtmltags = $allowed;
} }
public function qtype() {
return 'gapselect';
}
} }
......
...@@ -46,22 +46,25 @@ class qtype_multichoice_edit_form extends question_edit_form { ...@@ -46,22 +46,25 @@ class qtype_multichoice_edit_form extends question_edit_form {
); );
$mform->addElement('select', 'single', $mform->addElement('select', 'single',
get_string('answerhowmany', 'qtype_multichoice'), $menu); 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', $mform->addElement('advcheckbox', 'shuffleanswers',
get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0, 1)); get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0, 1));
$mform->addHelpButton('shuffleanswers', 'shuffleanswers', 'qtype_multichoice'); $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', $mform->addElement('select', 'answernumbering',
get_string('answernumbering', 'qtype_multichoice'), get_string('answernumbering', 'qtype_multichoice'),
qtype_multichoice::get_numbering_styles()); 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', $mform->addElement('selectyesno', 'showstandardinstruction',
get_string('showstandardinstruction', 'qtype_multichoice'), null, null, [0, 1]); get_string('showstandardinstruction', 'qtype_multichoice'), null, null, [0, 1]);
$mform->addHelpButton('showstandardinstruction', 'showstandardinstruction', 'qtype_multichoice'); $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}'), $this->add_per_answer_fields($mform, get_string('choiceno', 'qtype_multichoice', '{no}'),
question_bank::fraction_options_full(), max(5, QUESTION_NUMANS_START)); question_bank::fraction_options_full(), max(5, QUESTION_NUMANS_START));
......
...@@ -85,6 +85,14 @@ class qtype_multichoice extends question_type { ...@@ -85,6 +85,14 @@ class qtype_multichoice extends question_type {
return $options; 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) { public function save_question_options($question) {
global $DB; global $DB;
$context = $question->context; $context = $question->context;
......
...@@ -38,12 +38,17 @@ Feature: Test creating a Multiple choice question ...@@ -38,12 +38,17 @@ Feature: Test creating a Multiple choice question
| Hint 2 | Second hint | | Hint 2 | Second hint |
Then I should see "Multi-choice-001" Then I should see "Multi-choice-001"
@javascript
Scenario: Create a Multiple choice question with single response Scenario: Create a Multiple choice question with single response
When I add a "Multiple choice" question filling the form with: Given I add a "Multiple choice" question filling the form with:
| Question name | Multi-choice-002 | | Question name | Multi-choice-002 |
| Question text | Find the capital city of England. | | Question text | Find the capital city of England. |
| General feedback | London is the capital city of England. | | General feedback | London is the capital city of England. |
| Default mark | 5 |
| One or multiple answers? | One answer only | | 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 1 | Manchester |
| Choice 2 | Buckingham | | Choice 2 | Buckingham |
| Choice 3 | London | | Choice 3 | London |
...@@ -56,4 +61,14 @@ Feature: Test creating a Multiple choice question ...@@ -56,4 +61,14 @@ Feature: Test creating a Multiple choice question
| id_fraction_4 | None | | id_fraction_4 | None |
| Hint 1 | First hint | | Hint 1 | First hint |
| Hint 2 | Second hint | | Hint 2 | Second hint |
Then I should see "Multi-choice-002" 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 |
...@@ -295,6 +295,45 @@ class question_type { ...@@ -295,6 +295,45 @@ class question_type {
public function set_default_options($questiondata) { 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. * Saves (creates or updates) a question.
* *
......
...@@ -36,12 +36,13 @@ defined('MOODLE_INTERNAL') || die(); ...@@ -36,12 +36,13 @@ defined('MOODLE_INTERNAL') || die();
class qtype_shortanswer_edit_form extends question_edit_form { class qtype_shortanswer_edit_form extends question_edit_form {
protected function definition_inner($mform) { protected function definition_inner($mform) {
$menu = array( $menu = [
get_string('caseno', 'qtype_shortanswer'), get_string('caseno', 'qtype_shortanswer'),
get_string('caseyes', 'qtype_shortanswer') get_string('caseyes', 'qtype_shortanswer')
); ];
$mform->addElement('select', 'usecase', $mform->addElement('select', 'usecase',
get_string('casesensitive', 'qtype_shortanswer'), $menu); get_string('casesensitive', 'qtype_shortanswer'), $menu);
$mform->setDefault('usecase', $this->get_default_value('usecase', $menu[0]));
$mform->addElement('static', 'answersinstruct', $mform->addElement('static', 'answersinstruct',
get_string('correctanswers', 'qtype_shortanswer'), get_string('correctanswers', 'qtype_shortanswer'),
......
...@@ -54,6 +54,11 @@ class qtype_shortanswer extends question_type { ...@@ -54,6 +54,11 @@ class qtype_shortanswer extends question_type {
$this->delete_files_in_hints($questionid, $contextid); $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) { public function save_question_options($question) {
global $DB; global $DB;
$result = new stdClass(); $result = new stdClass();
......
...@@ -18,17 +18,24 @@ Feature: Test creating a Short answer question ...@@ -18,17 +18,24 @@ Feature: Test creating a Short answer question
And I am on "Course 1" course homepage And I am on "Course 1" course homepage
And I navigate to "Question bank" in current page administration And I navigate to "Question bank" in current page administration
@javascript
Scenario: Create a Short answer question 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 name | shortanswer-001 |
| Question text | What is the national langauge in France? | | Question text | What is the national langauge in France? |
| General feedback | The national langauge in France is French | | General feedback | The national langauge in France is French |
| Default mark | 1 | | Default mark | 1 |
| Case sensitivity | No, case is unimportant | | Case sensitivity | Yes, case must match |
| id_answer_0 | French | | id_answer_0 | French |
| id_fraction_0 | 100% | | id_fraction_0 | 100% |
| id_feedback_0 | Well done. French is correct. | | id_feedback_0 | Well done. French is correct. |
| id_answer_1 | * | | id_answer_1 | * |
| id_fraction_1 | None | | id_fraction_1 | None |
| id_feedback_1 | Your answer is incorrect. | | 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 |
This files describes API changes for question type plugins. 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 === === 3.8 ===
* There is a new method for question types get_extra_question_bank_actions. * There is a new method for question types get_extra_question_bank_actions.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment