From 706d06e29b0c2c5253a00b7cab0798cf0abd6b0d Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 1 Feb 2011 23:44:40 +0000 Subject: [PATCH] MDL-20636 ddwtos and gapselect qtypes now very nearly work. Todo rendering questions with files, and ddwtos javascript. --- question/type/ddwtos/db/install.xml | 11 +- question/type/ddwtos/db/upgrade.php | 83 ------------ question/type/ddwtos/edit_ddwtos_form.php | 33 ++--- question/type/ddwtos/{ => pix}/icon.gif | Bin question/type/ddwtos/questiontype.php | 2 +- question/type/gapselect/db/install.xml | 11 +- question/type/gapselect/edit_form_base.php | 97 +++++++------- .../type/gapselect/edit_gapselect_form.php | 21 --- .../gapselect/lang/en/qtype_gapselect.php | 4 +- question/type/gapselect/{ => pix}/icon.gif | Bin question/type/gapselect/questiontype.php | 2 +- question/type/gapselect/questiontypebase.php | 121 +++++++++--------- .../multichoice/edit_multichoice_form.php | 6 +- 13 files changed, 142 insertions(+), 249 deletions(-) delete mode 100644 question/type/ddwtos/db/upgrade.php rename question/type/ddwtos/{ => pix}/icon.gif (100%) rename question/type/gapselect/{ => pix}/icon.gif (100%) diff --git a/question/type/ddwtos/db/install.xml b/question/type/ddwtos/db/install.xml index 065853d37b1..50dbefe8a09 100644 --- a/question/type/ddwtos/db/install.xml +++ b/question/type/ddwtos/db/install.xml @@ -9,10 +9,13 @@ - - - - + + + + + + + diff --git a/question/type/ddwtos/db/upgrade.php b/question/type/ddwtos/db/upgrade.php deleted file mode 100644 index 91d665a1685..00000000000 --- a/question/type/ddwtos/db/upgrade.php +++ /dev/null @@ -1,83 +0,0 @@ -question = $ddanswer->questionid; - $answer->answer = addslashes($ddanswer->answer); - $answer->fraction = 1; - - $feedback = new stdClass; - $feedback->draggroup = $ddanswer->draggroup; - $feedback->infinite = $ddanswer->infinite; - $answer->feedback = serialize($feedback); - - if(!insert_record('question_answers', $answer)){ - notify('move_question_ddanswers_to_question_answers(): cannot insert row into question_answer table.'); - return false; - } - } - } - - // Drop table - $result = $result && drop_table($table); - } - - if ($result && $oldversion < 2010042800) { - - /// Rename field correctresponsesfeedback on table question_ddwtos to shownumcorrect - $table = new XMLDBTable('question_ddwtos'); - $field = new XMLDBField('correctresponsesfeedback'); - $field->setAttributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'incorrectfeedback'); - - /// Launch rename field correctresponsesfeedback - $result = $result && rename_field($table, $field, 'shownumcorrect'); - } - - return $result; -} diff --git a/question/type/ddwtos/edit_ddwtos_form.php b/question/type/ddwtos/edit_ddwtos_form.php index e04351c8e14..222aaf08fcd 100644 --- a/question/type/ddwtos/edit_ddwtos_form.php +++ b/question/type/ddwtos/edit_ddwtos_form.php @@ -34,36 +34,21 @@ require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { - function qtype() { return 'ddwtos'; } - protected function default_values_from_feedback_field($feedback, $key){ - $feedback = unserialize($feedback); - $draggroup = $feedback->draggroup; - $infinite = $feedback->infinite; - - $default_values = array(); - $default_values['choices['.$key.'][draggroup]'] = $draggroup; - $default_values['choices['.$key.'][infinite]'] = $infinite; - return $default_values; + protected function data_preprocessing_choice($question, $answer, $key) { + $question = parent::data_preprocessing_choice($question, $answer, $key); + $options = unserialize($answer->feedback); + $question->choices[$key]['choicegroup'] = $options->draggroup; + $question->choices[$key]['infinite'] = $options->infinite; + return $question; } - protected function repeated_options(){ - $repeatedoptions = array(); - $repeatedoptions['draggroup']['default'] = '1'; - $repeatedoptions['infinite']['default'] = 0; - return $repeatedoptions; - } - - protected function choice_group(&$mform, $grouparray){ - $options = array(); - for ($i = 1; $i <= 8; $i += 1) { - $options[$i] = $i; - } - $grouparray[] =& $mform->createElement('select', 'draggroup', get_string('group', 'qtype_ddwtos'), $options); - $grouparray[] =& $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddwtos'), null, array('size'=>1, 'class'=>'tweakcss')); + protected function choice_group($mform) { + $grouparray = parent::choice_group($mform); + $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddwtos'), null, array('size'=>1, 'class'=>'tweakcss')); return $grouparray; } } diff --git a/question/type/ddwtos/icon.gif b/question/type/ddwtos/pix/icon.gif similarity index 100% rename from question/type/ddwtos/icon.gif rename to question/type/ddwtos/pix/icon.gif diff --git a/question/type/ddwtos/questiontype.php b/question/type/ddwtos/questiontype.php index 94d121a634b..e360fcc15fb 100644 --- a/question/type/ddwtos/questiontype.php +++ b/question/type/ddwtos/questiontype.php @@ -48,7 +48,7 @@ class qtype_ddwtos extends qtype_gapselect_base { protected function choice_options_to_feedback($choice){ $output = new stdClass; - $output->draggroup = $choice['draggroup']; + $output->draggroup = $choice['choicegroup']; $output->infinite = !empty($choice['infinite']); return serialize($output); } diff --git a/question/type/gapselect/db/install.xml b/question/type/gapselect/db/install.xml index 0eb4f71451f..cfab23dfe01 100644 --- a/question/type/gapselect/db/install.xml +++ b/question/type/gapselect/db/install.xml @@ -9,10 +9,13 @@ - - - - + + + + + + + diff --git a/question/type/gapselect/edit_form_base.php b/question/type/gapselect/edit_form_base.php index 822eae2044f..26c97a01359 100644 --- a/question/type/gapselect/edit_form_base.php +++ b/question/type/gapselect/edit_form_base.php @@ -8,6 +8,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_gapselect_edit_form_base extends question_edit_form { + const MAX_GROUPS = 8; /** @var array of HTML tags allowed in choices / drag boxes. */ protected $allowedhtmltags = array( @@ -64,7 +65,7 @@ class qtype_gapselect_edit_form_base extends question_edit_form { * definition_inner adds all specific fields to the form. * @param object $mform (the form being built). */ - function definition_inner(&$mform) { + function definition_inner($mform) { global $CFG; //add the answer (choice) fields to the form @@ -75,19 +76,14 @@ class qtype_gapselect_edit_form_base extends question_edit_form { } protected function definition_answer_choice(&$mform) { - $mform->addElement('header', 'choicehdr', get_string('choices', 'qtype_gapselect')); + $mform->addElement('header', 'choicehdr', get_string('choices', 'qtype_gapselect')); - $mform->addElement('checkbox', 'shuffleanswers', get_string('shuffle', 'quiz')); + $mform->addElement('checkbox', 'shuffleanswers', get_string('shuffle', 'qtype_gapselect')); $mform->setDefault('shuffleanswers', 0); $textboxgroup = array(); - - $grouparray = array(); - $grouparray[] =& $mform->createElement('text', 'answer', get_string('answer', 'qtype_gapselect'), array('size'=>30, 'class'=>'tweakcss')); - $grouparray[] =& $mform->createElement('static', '', '',' '.get_string('group', 'qtype_gapselect').' '); - - $grouparray = $this->choice_group($mform, $grouparray); - $textboxgroup[] = $mform->createElement('group','choices', 'Choice {no}',$grouparray); + $textboxgroup[] = $mform->createElement('group', 'choices', + get_string('choicex', 'qtype_gapselect'), $this->choice_group($mform)); if (isset($this->question->options)) { $countanswers = count($this->question->options->answers); @@ -96,7 +92,7 @@ class qtype_gapselect_edit_form_base extends question_edit_form { } if ($this->question->formoptions->repeatelements) { - $defaultstartnumbers = QUESTION_NUMANS_START*2; + $defaultstartnumbers = QUESTION_NUMANS_START * 2; $repeatsatstart = max($defaultstartnumbers, QUESTION_NUMANS_START, $countanswers + QUESTION_NUMANS_ADD); } else { $repeatsatstart = $countanswers; @@ -107,29 +103,51 @@ class qtype_gapselect_edit_form_base extends question_edit_form { $this->repeat_elements($textboxgroup, $repeatsatstart, $repeatedoptions, 'noanswers', 'addanswers', QUESTION_NUMANS_ADD, get_string('addmorechoiceblanks', 'qtype_gapselect')); } - - - public function set_data($question) { - if (isset($question->options)) { - $options = $question->options; - $default_values = array(); - if (count($options->answers)) { - $key = 0; - foreach ($options->answers as $answer) { - $default_values['choices['.$key.'][answer]'] = $answer->answer; - $default_values += $this->default_values_from_feedback_field($answer->feedback, $key); - $key++; - } - } - - $default_values['shuffleanswers'] = $question->options->shuffleanswers; - $default_values['correctfeedback'] = $question->options->correctfeedback; - $default_values['partiallycorrectfeedback'] = $question->options->partiallycorrectfeedback; - $default_values['incorrectfeedback'] = $question->options->incorrectfeedback; - $default_values['shownumcorrect'] = $question->options->shownumcorrect; - $question = (object)((array)$question + $default_values); + protected function choice_group($mform) { + $options = array(); + for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { + $options[$i] = $i; } - parent::set_data($question); + $grouparray = array(); + $grouparray[] = $mform->createElement('text', 'answer', get_string('answer', 'qtype_gapselect'), array('size'=>30, 'class'=>'tweakcss')); + $grouparray[] = $mform->createElement('static', '', '',' '.get_string('group', 'qtype_gapselect').' '); + $grouparray[] = $mform->createElement('select', 'choicegroup', get_string('group', 'qtype_gapselect'), $options); + return $grouparray; + } + + protected function repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['choicegroup']['default'] = '1'; + return $repeatedoptions; + } + + public function data_preprocessing($question) { + $question = parent::data_preprocessing($question); + $question = $this->data_preprocessing_combined_feedback($question, true); + $question = $this->data_preprocessing_hints($question, true, true); + + $question = $this->data_preprocessing_answers($question, true); + if (!empty($question->options->answers)) { + $key = 0; + foreach ($question->options->answers as $answer) { + $question = $this->data_preprocessing_choice($question, $answer, $key); + $key++; + } + } + + if (!empty($question->options)) { + $question->shuffleanswers = $question->options->shuffleanswers; + } + + return $question; + } + + protected function data_preprocessing_choice($question, $answer, $key) { + // See comment in data_preprocessing_answers. + unset($this->_form->_defaultValues['choices[$key][choicegroup]']); + $question->choices[$key]['answer'] = $answer->answer; + $question->choices[$key]['choicegroup'] = $answer->feedback; + return $question; } public function validation($data, $files) { @@ -138,7 +156,7 @@ class qtype_gapselect_edit_form_base extends question_edit_form { $choices = $data['choices']; //check the whether the slots are valid - $errorsinquestiontext = $this->validate_slots($questiontext, $choices); + $errorsinquestiontext = $this->validate_slots($questiontext['text'], $choices); if ($errorsinquestiontext) { $errors['questiontext'] = $errorsinquestiontext; } @@ -196,17 +214,8 @@ class qtype_gapselect_edit_form_base extends question_edit_form { } return false; } + function qtype() { return ''; } - - protected function default_values_from_feedback_field($feedback, $key) { - $default_values = array(); - return $default_values; - } - - protected function repeated_options() { - $repeatedoptions = array(); - return $repeatedoptions; - } } \ No newline at end of file diff --git a/question/type/gapselect/edit_gapselect_form.php b/question/type/gapselect/edit_gapselect_form.php index 62ab9c6e92f..cb5cf44657c 100644 --- a/question/type/gapselect/edit_gapselect_form.php +++ b/question/type/gapselect/edit_gapselect_form.php @@ -35,31 +35,10 @@ require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_gapselect_edit_form extends qtype_gapselect_edit_form_base { - // HTML tags allowed in answers (choices). protected $allowedhtmltags = array(); function qtype() { return 'gapselect'; } - - protected function default_values_from_feedback_field($feedback, $key) { - $default_values = array(); - $default_values['choices['.$key.'][selectgroup]'] = $feedback; - return $default_values; - } - - protected function repeated_options() { - $repeatedoptions = array(); - $repeatedoptions['selectgroup']['default'] = '1'; - return $repeatedoptions; - } - protected function choice_group(&$mform, $grouparray) { - $options = array(); - for ($i = 1; $i <= 8; $i += 1) { - $options[$i] = $i; - } - $grouparray[] =& $mform->createElement('select', 'selectgroup', get_string('group', 'qtype_gapselect'), $options); - return $grouparray; - } } diff --git a/question/type/gapselect/lang/en/qtype_gapselect.php b/question/type/gapselect/lang/en/qtype_gapselect.php index 099b40b3ae4..5cce5c2354a 100644 --- a/question/type/gapselect/lang/en/qtype_gapselect.php +++ b/question/type/gapselect/lang/en/qtype_gapselect.php @@ -30,10 +30,12 @@ $string['addinggapselect'] = 'Adding a select missing words question'; $string['addmorechoiceblanks'] = 'Blanks for {no} more choices'; $string['answer'] = 'Answer'; $string['choices'] = 'Choices'; +$string['choicex'] = 'Choice {no}'; $string['correctansweris'] = 'The correct answer is: {$a}'; +$string['editinggapselect'] = 'Editing a select missing words question'; $string['gapselect'] = 'Select missing words'; $string['gapselect_help'] = 'Type in some question text like "The [[1]] jumped over the [[2]]", then enter the possible words to go in gaps 1 and 2 underneath.'; $string['gapselectsummary'] = 'Missing words in some text are filled in using dropdown menus.'; -$string['editinggapselect'] = 'Editing a select missing words question'; $string['group'] = 'Group'; $string['pleaseputananswerineachbox'] = 'Please put an answer in each box.'; +$string['shuffle'] = 'Shuffle'; diff --git a/question/type/gapselect/icon.gif b/question/type/gapselect/pix/icon.gif similarity index 100% rename from question/type/gapselect/icon.gif rename to question/type/gapselect/pix/icon.gif diff --git a/question/type/gapselect/questiontype.php b/question/type/gapselect/questiontype.php index 736eb5c8d61..dc4af4c00ac 100644 --- a/question/type/gapselect/questiontype.php +++ b/question/type/gapselect/questiontype.php @@ -40,7 +40,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); */ class qtype_gapselect extends qtype_gapselect_base { protected function choice_options_to_feedback($choice) { - return $choice['selectgroup']; + return $choice['choicegroup']; } protected function make_choice($choicedata) { diff --git a/question/type/gapselect/questiontypebase.php b/question/type/gapselect/questiontypebase.php index 7b3b336c63f..472fbac651a 100644 --- a/question/type/gapselect/questiontypebase.php +++ b/question/type/gapselect/questiontypebase.php @@ -49,11 +49,12 @@ abstract class qtype_gapselect_base extends question_type { protected abstract function choice_options_to_feedback($choice); public function save_question_options($question) { + global $DB; + $context = $question->context; $result = new stdClass(); - if (!$oldanswers = get_records('question_answers', 'question', $question->id, 'id ASC')) { - $oldanswers = array(); - } + $oldanswers = $DB->get_records('question_answers', + array('question' => $question->id), 'id ASC'); // Insert all the new answers foreach ($question->choices as $key => $choice) { @@ -64,80 +65,56 @@ abstract class qtype_gapselect_base extends question_type { $feedback = $this->choice_options_to_feedback($choice); - if ($answer = array_shift($oldanswers)) { // Existing answer, so reuse it + if ($answer = array_shift($oldanswers)) { $answer->answer = $choice['answer']; - $answer->fraction = 0; $answer->feedback = $feedback; - if (!update_record('question_answers', $answer)) { - $result->error = "Could not update question type '".$this->name()."' question answer! (id=$answer->id)"; - return $result; - } + $DB->update_record('question_answers', $answer); + } else { - $answer = new stdClass; - $answer->answer = $choice['answer']; + $answer = new stdClass(); $answer->question = $question->id; + $answer->answer = $choice['answer']; + $answer->answerformat = FORMAT_HTML; $answer->fraction = 0; $answer->feedback = $feedback; - if (!$answer->id = insert_record('question_answers', $answer)) { - $result->error = 'Could not insert question type \''.$this->name().'\' question answer!'; - return $result; - } + $answer->feedbackformat = 0; + $DB->insert_record('question_answers', $answer); } } // Delete old answer records - if (!empty($oldanswers)) { - foreach($oldanswers as $oa) { - delete_records('question_answers', 'id', $oa->id); - } + foreach($oldanswers as $oa) { + delete_records('question_answers', 'id', $oa->id); } - $update = true; - $options = get_record('question_' . $this->name(), 'questionid', $question->id); + $options = $DB->get_record('question_' . $this->name(), array('questionid' => $question->id)); if (!$options) { - $update = false; - $options = new stdClass; + $options = new stdClass(); $options->questionid = $question->id; + $options->correctfeedback = ''; + $options->partiallycorrectfeedback = ''; + $options->incorrectfeedback = ''; + $options->id = $DB->insert_record('question_' . $this->name(), $options); } $options->shuffleanswers = !empty($question->shuffleanswers); - $options->correctfeedback = trim($question->correctfeedback); - $options->partiallycorrectfeedback = trim($question->partiallycorrectfeedback); - $options->shownumcorrect = !empty($question->shownumcorrect); - $options->incorrectfeedback = trim($question->incorrectfeedback); - - if ($update) { - if (!update_record('question_'.$this->name(), $options)) { - $result->error = "Could not update question type '".$this->name()."' options! (id=$options->id)"; - return $result; - } - - } else { - if (!insert_record('question_gapselect', $options)) { - $result->error = 'Could not insert question type \''.$this->name().'\' options!'; - return $result; - } - } + $options = $this->save_combined_feedback_helper($options, $question, $context, true); + $DB->update_record('question_' . $this->name(), $options); $this->save_hints($question, true); - - return true; } public function get_question_options($question) { - // Get additional information from database and attach it to the question object - if (!$question->options = get_record('question_'.$this->name(), 'questionid', $question->id)) { - notify('Error: Missing question options for question type \''.$this->name().'\' question '.$question->id.'!'); - return false; - } - + global $DB; + $question->options = $DB->get_record('question_'.$this->name(), + array('questionid' => $question->id), '*', MUST_EXIST); parent::get_question_options($question); - return true; } - public function delete_question($questionid) { - delete_records('question_'.$this->name(), 'questionid', $questionid); - return parent::delete_question($questionid); + public function delete_question($questionid, $contextid) { + global $DB; + $DB->delete_records('question_'.$this->name(), array('questionid' => $questionid)); + return parent::delete_question($questionid, $contextid); } /** @@ -261,15 +238,15 @@ abstract class qtype_gapselect_base extends question_type { $arrayofchoices = $this->get_array_of_choices($question); $arrayofplaceholdeers = $this->get_array_of_placeholders($question); - $correctplayeers = array(); + $correctplayers = array(); foreach($arrayofplaceholdeers as $ph) { foreach($arrayofchoices as $key=>$choice) { if(($key+1) == $ph) { - $correctplayeers[]= $choice; + $correctplayers[]= $choice; } } } - return $correctplayeers; + return $correctplayers; } protected function get_array_of_placeholders($question) { @@ -290,22 +267,21 @@ abstract class qtype_gapselect_base extends question_type { $output = array(); foreach ($slots as $slot) { - $output[]=substr($slot, 2, (strlen($slot)-4));//2 is for'[[' and 4 is for '[[]]' + $output[] = substr($slot, 2, strlen($slot) - 4); //2 is for '[[' and 4 is for '[[]]'. } return $output; } - protected function get_group_of_players ($question, $state, $subquestions, $group) { - $goupofanswers=array(); - foreach($subquestions as $key=>$subquestion) { - if($subquestion[$this->choice_group_key()] == $group) { - $goupofanswers[] = $subquestion; + protected function get_group_of_players($question, $state, $subquestions, $group) { + $goupofanswers = array(); + foreach ($subquestions as $key => $subquestion) { + if ($subquestion[$this->choice_group_key()] == $group) { + $goupofanswers[] = $subquestion; } } - //shuffle answers within this group + // Shuffle answers within this group if ($question->options->shuffleanswers == 1) { - srand($state->attempt); shuffle($goupofanswers); } return $goupofanswers; @@ -331,5 +307,24 @@ abstract class qtype_gapselect_base extends question_type { return $parts; } + function move_files($questionid, $oldcontextid, $newcontextid) { + parent::move_files($questionid, $oldcontextid, $newcontextid); + $fs = get_file_storage(); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'question', 'correctfeedback', $questionid); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'question', 'partiallycorrectfeedback', $questionid); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'question', 'incorrectfeedback', $questionid); + } + + protected function delete_files($questionid, $contextid) { + parent::delete_files($questionid, $contextid); + + $fs = get_file_storage(); + $fs->delete_area_files($contextid, 'question', 'correctfeedback', $questionid); + $fs->delete_area_files($contextid, 'question', 'partiallycorrectfeedback', $questionid); + $fs->delete_area_files($contextid, 'question', 'incorrectfeedback', $questionid); + } } diff --git a/question/type/multichoice/edit_multichoice_form.php b/question/type/multichoice/edit_multichoice_form.php index ad5eba0f8dc..59c4555eaa7 100644 --- a/question/type/multichoice/edit_multichoice_form.php +++ b/question/type/multichoice/edit_multichoice_form.php @@ -70,9 +70,9 @@ class qtype_multichoice_edit_form extends question_edit_form { $question = $this->data_preprocessing_hints($question, true, true); if (!empty($question->options)) { - $question->single = $question->options->single; - $question->shuffleanswers = $question->options->shuffleanswers; - $question->answernumbering = $question->options->answernumbering; + $question->single = $question->options->single; + $question->shuffleanswers = $question->options->shuffleanswers; + $question->answernumbering = $question->options->answernumbering; } return $question;