MDL-79863 qtype_ordering: Save hints as the question author wants them (#75)
There was some old code that forced all questions to have at least 2 hints, but we have teachers who want exactly one hint for a question in their exams. Also, the hint-saving code was duplicating a lot of core code, so I cleaned it up.
This commit is contained in:
@@ -242,86 +242,39 @@ class qtype_ordering extends question_type {
|
||||
* @return int Count of hints on the form.
|
||||
*/
|
||||
protected function count_hints_on_form($formdata, $withparts) {
|
||||
if (!empty($formdata->hint)) {
|
||||
$numhints = max(array_keys($formdata->hint)) + 1;
|
||||
} else {
|
||||
$numhints = 0;
|
||||
$numhints = parent::count_hints_on_form($formdata, $withparts);
|
||||
|
||||
if (!empty($formdata->hintoptions)) {
|
||||
$numhints = max($numhints, max(array_keys($formdata->hintoptions)) + 1);
|
||||
}
|
||||
|
||||
if ($withparts) {
|
||||
if (!empty($formdata->hintclearwrong)) {
|
||||
$numclears = max(array_keys($formdata->hintclearwrong)) + 1;
|
||||
} else {
|
||||
$numclears = 0;
|
||||
}
|
||||
if (!empty($formdata->hintshownumcorrect)) {
|
||||
$numshows = max(array_keys($formdata->hintshownumcorrect)) + 1;
|
||||
} else {
|
||||
$numshows = 0;
|
||||
}
|
||||
if (!empty($formdata->hintoptions)) {
|
||||
$numhighlights = max(array_keys($formdata->hintoptions)) + 1;
|
||||
} else {
|
||||
$numhighlights = 0;
|
||||
}
|
||||
|
||||
$numhints = max($numhints, $numclears, $numshows, $numhighlights);
|
||||
}
|
||||
return $numhints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save hints from the form. Overwrite save_hints function to custom hint controls.
|
||||
* Determine if the hint with specified number is not empty and should be saved.
|
||||
* Overload if you use custom hint controls.
|
||||
*
|
||||
* @param object $formdata The data from the form.
|
||||
* @param bool $withparts Whether to take into account clearwrong, shownumcorrect, and highlightresponse options.
|
||||
* @param object $formdata the data from the form.
|
||||
* @param int $number number of hint under question.
|
||||
* @param bool $withparts whether to take into account clearwrong and shownumcorrect options.
|
||||
* @return bool is this particular hint data empty.
|
||||
*/
|
||||
public function save_hints($formdata, $withparts = false) {
|
||||
global $DB;
|
||||
$context = $formdata->context;
|
||||
protected function is_hint_empty_in_form_data($formdata, $number, $withparts) {
|
||||
return parent::is_hint_empty_in_form_data($formdata, $number, $withparts) &&
|
||||
empty($formdata->hintoptions[$number]);
|
||||
}
|
||||
|
||||
$oldhints = $DB->get_records('question_hints',
|
||||
array('questionid' => $formdata->id), 'id ASC');
|
||||
|
||||
$numhints = $this->count_hints_on_form($formdata, $withparts);
|
||||
|
||||
for ($i = 0; $i < $numhints; $i += 1) {
|
||||
if (html_is_blank($formdata->hint[$i]['text'])) {
|
||||
$formdata->hint[$i]['text'] = '';
|
||||
}
|
||||
|
||||
if ($withparts) {
|
||||
$clearwrong = !empty($formdata->hintclearwrong[$i]);
|
||||
$shownumcorrect = !empty($formdata->hintshownumcorrect[$i]);
|
||||
$highlightresponse = !empty($formdata->hintoptions[$i]);
|
||||
}
|
||||
|
||||
// Update an existing hint if possible.
|
||||
$hint = array_shift($oldhints);
|
||||
if (!$hint) {
|
||||
$hint = new stdClass();
|
||||
$hint->questionid = $formdata->id;
|
||||
$hint->hint = '';
|
||||
$hint->id = $DB->insert_record('question_hints', $hint);
|
||||
}
|
||||
|
||||
$hint->hint = $this->import_or_save_files($formdata->hint[$i],
|
||||
$context, 'question', 'hint', $hint->id);
|
||||
$hint->hintformat = $formdata->hint[$i]['format'];
|
||||
if ($withparts) {
|
||||
$hint->clearwrong = $clearwrong;
|
||||
$hint->shownumcorrect = $shownumcorrect;
|
||||
$hint->options = $highlightresponse;
|
||||
}
|
||||
$DB->update_record('question_hints', $hint);
|
||||
}
|
||||
|
||||
// Delete any remaining old hints.
|
||||
$fs = get_file_storage();
|
||||
foreach ($oldhints as $oldhint) {
|
||||
$fs->delete_area_files($context->id, 'question', 'hint', $oldhint->id);
|
||||
$DB->delete_records('question_hints', array('id' => $oldhint->id));
|
||||
}
|
||||
/**
|
||||
* Save additional question type data into the hint optional field.
|
||||
* Overload if you use custom hint information.
|
||||
* @param object $formdata the data from the form.
|
||||
* @param int $number number of hint to get options from.
|
||||
* @param bool $withparts whether question have parts.
|
||||
* @return string value to save into the options field of question_hints table.
|
||||
*/
|
||||
protected function save_hint_options($formdata, $number, $withparts) {
|
||||
return !empty($formdata->hintoptions[$number]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,31 +379,6 @@ class qtype_ordering extends question_type {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the shownumcorrect and highlight options with the old question when restoring.
|
||||
$hints = $DB->get_records('question_hints', ['questionid' => $question->id], 'id ASC');
|
||||
$counthints = count($hints);
|
||||
for ($i = 0; $i < max(self::DEFAULT_NUM_HINTS, $counthints); $i++) {
|
||||
$hint = array_shift($hints);
|
||||
if (!$hint) {
|
||||
$hint = new stdClass();
|
||||
$hint->questionid = $question->id;
|
||||
$hint->hint = '';
|
||||
$hint->hintformat = 1;
|
||||
$hint->clearwrong = 0;
|
||||
$hint->options = 1;
|
||||
$hint->shownumcorrect = 1;
|
||||
$hint->id = $DB->insert_record('question_hints', $hint);
|
||||
}
|
||||
|
||||
if (isset($hint->shownumcorrect) || isset($hint->options)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hint->options = 1;
|
||||
$hint->shownumcorrect = 1;
|
||||
$DB->update_record('question_hints', $hint);
|
||||
}
|
||||
|
||||
parent::get_question_options($question);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,3 +37,18 @@ Feature: Test creating an Ordering question
|
||||
| hintshownumcorrect[1] | 1 |
|
||||
| shownumcorrect | 1 |
|
||||
Then I should see "Ordering-001"
|
||||
|
||||
Scenario: Ordering questions are created with only the number of hints that are defined
|
||||
Given the following config values are set as admin:
|
||||
| behaviour | interactive | question_preview |
|
||||
When I add a "Ordering" question filling the form with:
|
||||
| Question name | Ordering with one hint |
|
||||
| Question text | Put the words in correct order. |
|
||||
| id_answer_0 | one |
|
||||
| id_answer_1 | two |
|
||||
| id_answer_2 | three |
|
||||
| Hint 1 | This is the first and only hint. |
|
||||
| hintoptions[0] | 1 |
|
||||
And I should see "Ordering with one hint"
|
||||
When I am on the "Ordering with one hint" "core_question > preview" page
|
||||
Then I should see "Tries remaining: 2"
|
||||
|
||||
@@ -44,7 +44,7 @@ Feature: Test duplicating a quiz containing a Ordering question
|
||||
| For any partially correct response | Parts, but only parts, of your response are correct. |
|
||||
| For any incorrect response | That is not right at all. |
|
||||
| id_shownumcorrect | 1 |
|
||||
| id_hintshownumcorrect_0 | 1 |
|
||||
| id_hintoptions_0 | 1 |
|
||||
| id_hintshownumcorrect_1 | 1 |
|
||||
| id_hintoptions_1 | 1 |
|
||||
| id_hintshownumcorrect_0 | 0 |
|
||||
| id_hintoptions_0 | 0 |
|
||||
| id_hintshownumcorrect_1 | 0 |
|
||||
| id_hintoptions_1 | 0 |
|
||||
|
||||
Reference in New Issue
Block a user