Skip to content

Commit

Permalink
Save hints as the question author wants them (#75)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
timhunt authored Sep 12, 2023
1 parent c3aaff1 commit 2a76b33
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 100 deletions.
120 changes: 24 additions & 96 deletions questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,86 +242,39 @@ public function save_question_options($question) {
* @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;
}

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 = parent::count_hints_on_form($formdata, $withparts);

$numhints = max($numhints, $numclears, $numshows, $numhighlights);
if (!empty($formdata->hintoptions)) {
$numhints = max($numhints, max(array_keys($formdata->hintoptions)) + 1);
}

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;

$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);
}
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]);
}

// 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]);
}

/**
Expand Down Expand Up @@ -426,31 +379,6 @@ public function get_question_options($question) {
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;
}
Expand Down
15 changes: 15 additions & 0 deletions tests/behat/add.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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"
8 changes: 4 additions & 4 deletions tests/behat/backup_and_restore.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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 |

0 comments on commit 2a76b33

Please sign in to comment.