Commit 6189fda4 authored by John Beedell's avatar John Beedell
Browse files

MDL-62708 question: Add idnumbers to question and question category

parent 6902f391
...@@ -2211,7 +2211,7 @@ class backup_questions_structure_step extends backup_structure_step { ...@@ -2211,7 +2211,7 @@ class backup_questions_structure_step extends backup_structure_step {
$qcategory = new backup_nested_element('question_category', array('id'), array( $qcategory = new backup_nested_element('question_category', array('id'), array(
'name', 'contextid', 'contextlevel', 'contextinstanceid', 'name', 'contextid', 'contextlevel', 'contextinstanceid',
'info', 'infoformat', 'stamp', 'parent', 'info', 'infoformat', 'stamp', 'parent',
'sortorder')); 'sortorder', 'idnumber'));
$questions = new backup_nested_element('questions'); $questions = new backup_nested_element('questions');
...@@ -2219,7 +2219,7 @@ class backup_questions_structure_step extends backup_structure_step { ...@@ -2219,7 +2219,7 @@ class backup_questions_structure_step extends backup_structure_step {
'parent', 'name', 'questiontext', 'questiontextformat', 'parent', 'name', 'questiontext', 'questiontextformat',
'generalfeedback', 'generalfeedbackformat', 'defaultmark', 'penalty', 'generalfeedback', 'generalfeedbackformat', 'defaultmark', 'penalty',
'qtype', 'length', 'stamp', 'version', 'qtype', 'length', 'stamp', 'version',
'hidden', 'timecreated', 'timemodified', 'createdby', 'modifiedby')); 'hidden', 'timecreated', 'timemodified', 'createdby', 'modifiedby', 'idnumber'));
// attach qtype plugin structure to $question element, only one allowed // attach qtype plugin structure to $question element, only one allowed
$this->add_plugin_structure('qtype', $question, false); $this->add_plugin_structure('qtype', $question, false);
......
...@@ -4434,6 +4434,12 @@ class restore_create_categories_and_questions extends restore_structure_step { ...@@ -4434,6 +4434,12 @@ class restore_create_categories_and_questions extends restore_structure_step {
$data->stamp = make_unique_id_code(); $data->stamp = make_unique_id_code();
} }
// The idnumber if it exists also needs to be unique within a context or reset it to null.
if (!empty($data->idnumber) && $DB->record_exists('question_categories',
['idnumber' => $data->idnumber, 'contextid' => $data->contextid])) {
unset($data->idnumber);
}
// Let's create the question_category and save mapping. // Let's create the question_category and save mapping.
$newitemid = $DB->insert_record('question_categories', $data); $newitemid = $DB->insert_record('question_categories', $data);
$this->set_mapping('question_category', $oldid, $newitemid); $this->set_mapping('question_category', $oldid, $newitemid);
...@@ -4479,6 +4485,13 @@ class restore_create_categories_and_questions extends restore_structure_step { ...@@ -4479,6 +4485,13 @@ class restore_create_categories_and_questions extends restore_structure_step {
// With newitemid = 0, let's create the question // With newitemid = 0, let's create the question
if (!$questionmapping->newitemid) { if (!$questionmapping->newitemid) {
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (!empty($data->idnumber) && $DB->record_exists('question',
['idnumber' => $data->idnumber, 'category' => $data->category])) {
unset($data->idnumber);
}
$newitemid = $DB->insert_record('question', $data); $newitemid = $DB->insert_record('question', $data);
$this->set_mapping('question', $oldid, $newitemid); $this->set_mapping('question', $oldid, $newitemid);
// Also annotate them as question_created, we need // Also annotate them as question_created, we need
......
...@@ -170,6 +170,8 @@ $string['getcontextfromfile'] = 'Get context from file'; ...@@ -170,6 +170,8 @@ $string['getcontextfromfile'] = 'Get context from file';
$string['changepublishstatuscat'] = '<a href="{$a->caturl}">Category "{$a->name}"</a> in course "{$a->coursename}" will have it\'s sharing status changed from <strong>{$a->changefrom} to {$a->changeto}</strong>.'; $string['changepublishstatuscat'] = '<a href="{$a->caturl}">Category "{$a->name}"</a> in course "{$a->coursename}" will have it\'s sharing status changed from <strong>{$a->changefrom} to {$a->changeto}</strong>.';
$string['chooseqtypetoadd'] = 'Choose a question type to add'; $string['chooseqtypetoadd'] = 'Choose a question type to add';
$string['editquestions'] = 'Edit questions'; $string['editquestions'] = 'Edit questions';
$string['idnumber'] = 'ID number';
$string['idnumber_help'] = 'If used, the ID number must be unique within each question category. It provides another way of identifying a question which is sometimes useful, but can usually be left blank.';
$string['ignorebroken'] = 'Ignore broken links'; $string['ignorebroken'] = 'Ignore broken links';
$string['impossiblechar'] = 'Impossible character {$a} detected as parenthesis character'; $string['impossiblechar'] = 'Impossible character {$a} detected as parenthesis character';
$string['import'] = 'Import'; $string['import'] = 'Import';
......
...@@ -1333,6 +1333,7 @@ ...@@ -1333,6 +1333,7 @@
<FIELD NAME="stamp" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/> <FIELD NAME="stamp" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="parent" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="parent" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="999" SEQUENCE="false"/> <FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="999" SEQUENCE="false"/>
<FIELD NAME="idnumber" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
</FIELDS> </FIELDS>
<KEYS> <KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/> <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
...@@ -1341,6 +1342,7 @@ ...@@ -1341,6 +1342,7 @@
<INDEXES> <INDEXES>
<INDEX NAME="contextid" UNIQUE="false" FIELDS="contextid" COMMENT="links to context table"/> <INDEX NAME="contextid" UNIQUE="false" FIELDS="contextid" COMMENT="links to context table"/>
<INDEX NAME="contextidstamp" UNIQUE="true" FIELDS="contextid, stamp"/> <INDEX NAME="contextidstamp" UNIQUE="true" FIELDS="contextid, stamp"/>
<INDEX NAME="contextididnumber" UNIQUE="true" FIELDS="contextid, idnumber"/>
</INDEXES> </INDEXES>
</TABLE> </TABLE>
<TABLE NAME="question" COMMENT="The questions themselves"> <TABLE NAME="question" COMMENT="The questions themselves">
...@@ -1364,6 +1366,7 @@ ...@@ -1364,6 +1366,7 @@
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="time that question was last modified"/> <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="time that question was last modified"/>
<FIELD NAME="createdby" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="userid of person who created this question"/> <FIELD NAME="createdby" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="userid of person who created this question"/>
<FIELD NAME="modifiedby" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="userid of person who last edited this question"/> <FIELD NAME="modifiedby" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="userid of person who last edited this question"/>
<FIELD NAME="idnumber" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
</FIELDS> </FIELDS>
<KEYS> <KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/> <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
...@@ -1374,6 +1377,7 @@ ...@@ -1374,6 +1377,7 @@
</KEYS> </KEYS>
<INDEXES> <INDEXES>
<INDEX NAME="qtype" UNIQUE="false" FIELDS="qtype"/> <INDEX NAME="qtype" UNIQUE="false" FIELDS="qtype"/>
<INDEX NAME="categoryidnumber" UNIQUE="true" FIELDS="category, idnumber"/>
</INDEXES> </INDEXES>
</TABLE> </TABLE>
<TABLE NAME="question_answers" COMMENT="Answers, with a fractional grade (0-1) and feedback"> <TABLE NAME="question_answers" COMMENT="Answers, with a fractional grade (0-1) and feedback">
...@@ -3861,4 +3865,4 @@ ...@@ -3861,4 +3865,4 @@
</INDEXES> </INDEXES>
</TABLE> </TABLE>
</TABLES> </TABLES>
</XMLDB> </XMLDB>
\ No newline at end of file
...@@ -2360,5 +2360,44 @@ function xmldb_main_upgrade($oldversion) { ...@@ -2360,5 +2360,44 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2018091700.01); upgrade_main_savepoint(true, 2018091700.01);
} }
// Add idnumber fields to question and question_category tables.
// This is done in four parts to aid error recovery during upgrade, should that occur.
if ($oldversion < 2018092100.01) {
$table = new xmldb_table('question');
$field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'modifiedby');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_main_savepoint(true, 2018092100.01);
}
if ($oldversion < 2018092100.02) {
$table = new xmldb_table('question');
$index = new xmldb_index('categoryidnumber', XMLDB_INDEX_UNIQUE, array('category, idnumber'));
if (!$dbman->index_exists($table, $index)) {
$dbman->add_index($table, $index);
}
upgrade_main_savepoint(true, 2018092100.02);
}
if ($oldversion < 2018092100.03) {
$table = new xmldb_table('question_categories');
$field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'sortorder');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_main_savepoint(true, 2018092100.03);
}
if ($oldversion < 2018092100.04) {
$table = new xmldb_table('question_categories');
$index = new xmldb_index('contextididnumber', XMLDB_INDEX_UNIQUE, array('contextid, idnumber'));
if (!$dbman->index_exists($table, $index)) {
$dbman->add_index($table, $index);
}
// Main savepoint reached.
upgrade_main_savepoint(true, 2018092100.04);
}
return true; return true;
} }
...@@ -673,7 +673,7 @@ function question_move_questions_to_category($questionids, $newcategoryid) { ...@@ -673,7 +673,7 @@ function question_move_questions_to_category($questionids, $newcategoryid) {
array('id' => $newcategoryid)); array('id' => $newcategoryid));
list($questionidcondition, $params) = $DB->get_in_or_equal($questionids); list($questionidcondition, $params) = $DB->get_in_or_equal($questionids);
$questions = $DB->get_records_sql(" $questions = $DB->get_records_sql("
SELECT q.id, q.qtype, qc.contextid SELECT q.id, q.qtype, qc.contextid, q.idnumber
FROM {question} q FROM {question} q
JOIN {question_categories} qc ON q.category = qc.id JOIN {question_categories} qc ON q.category = qc.id
WHERE q.id $questionidcondition", $params); WHERE q.id $questionidcondition", $params);
...@@ -682,6 +682,27 @@ function question_move_questions_to_category($questionids, $newcategoryid) { ...@@ -682,6 +682,27 @@ function question_move_questions_to_category($questionids, $newcategoryid) {
question_bank::get_qtype($question->qtype)->move_files( question_bank::get_qtype($question->qtype)->move_files(
$question->id, $question->contextid, $newcontextid); $question->id, $question->contextid, $newcontextid);
} }
// Check whether there could be a clash of idnumbers in the new category.
if (((string) $question->idnumber !== '') &&
$DB->record_exists('question', ['idnumber' => $question->idnumber, 'category' => $newcategoryid])) {
$rec = $DB->get_records_select('question', "category = ? AND idnumber LIKE ?",
[$newcategoryid, $question->idnumber . '_%'], 'idnumber DESC', 'id, idnumber', 0, 1);
$unique = 1;
if (count($rec)) {
$rec = reset($rec);
$idnumber = $rec->idnumber;
if (strpos($idnumber, '_') !== false) {
$unique = substr($idnumber, strpos($idnumber, '_') + 1) + 1;
}
}
// For the move process, add a numerical increment to the idnumber. This means that if a question is
// mistakenly moved then the idnumber will not be completely lost.
$q = new stdClass();
$q->id = $question->id;
$q->category = $newcategoryid;
$q->idnumber = $question->idnumber . '_' . $unique;
$DB->update_record('question', $q);
}
} }
// Move the questions themselves. // Move the questions themselves.
......
...@@ -118,10 +118,10 @@ if ($qcobject->catform->is_cancelled()) { ...@@ -118,10 +118,10 @@ if ($qcobject->catform->is_cancelled()) {
$catformdata->info = $catformdata->info['text']; $catformdata->info = $catformdata->info['text'];
if (!$catformdata->id) {//new category if (!$catformdata->id) {//new category
$qcobject->add_category($catformdata->parent, $catformdata->name, $qcobject->add_category($catformdata->parent, $catformdata->name,
$catformdata->info, false, $catformdata->infoformat); $catformdata->info, false, $catformdata->infoformat, $catformdata->idnumber);
} else { } else {
$qcobject->update_category($catformdata->id, $catformdata->parent, $qcobject->update_category($catformdata->id, $catformdata->parent,
$catformdata->name, $catformdata->info, $catformdata->infoformat); $catformdata->name, $catformdata->info, $catformdata->infoformat, $catformdata->idnumber);
} }
redirect($thispageurl); redirect($thispageurl);
} else if ((!empty($param->delete) and (!$questionstomove) and confirm_sesskey())) { } else if ((!empty($param->delete) and (!$questionstomove) and confirm_sesskey())) {
......
...@@ -404,7 +404,8 @@ class question_category_object { ...@@ -404,7 +404,8 @@ class question_category_object {
/** /**
* Creates a new category with given params * Creates a new category with given params
*/ */
public function add_category($newparent, $newcategory, $newinfo, $return = false, $newinfoformat = FORMAT_HTML) { public function add_category($newparent, $newcategory, $newinfo, $return = false, $newinfoformat = FORMAT_HTML,
$idnumber = null) {
global $DB; global $DB;
if (empty($newcategory)) { if (empty($newcategory)) {
print_error('categorynamecantbeblank', 'question'); print_error('categorynamecantbeblank', 'question');
...@@ -419,6 +420,14 @@ class question_category_object { ...@@ -419,6 +420,14 @@ class question_category_object {
} }
} }
if (((string) $idnumber !== '') && !empty($contextid)) {
// While this check already exists in the form validation, this is a backstop preventing unnecessary errors.
if ($DB->record_exists('question_categories',
['idnumber' => $idnumber, 'contextid' => $contextid])) {
$idnumber = null;
}
}
$cat = new stdClass(); $cat = new stdClass();
$cat->parent = $parentid; $cat->parent = $parentid;
$cat->contextid = $contextid; $cat->contextid = $contextid;
...@@ -427,6 +436,9 @@ class question_category_object { ...@@ -427,6 +436,9 @@ class question_category_object {
$cat->infoformat = $newinfoformat; $cat->infoformat = $newinfoformat;
$cat->sortorder = 999; $cat->sortorder = 999;
$cat->stamp = make_unique_id_code(); $cat->stamp = make_unique_id_code();
if ($idnumber) {
$cat->idnumber = $idnumber;
}
$categoryid = $DB->insert_record("question_categories", $cat); $categoryid = $DB->insert_record("question_categories", $cat);
// Log the creation of this category. // Log the creation of this category.
...@@ -447,7 +459,8 @@ class question_category_object { ...@@ -447,7 +459,8 @@ class question_category_object {
/** /**
* Updates an existing category with given params * Updates an existing category with given params
*/ */
public function update_category($updateid, $newparent, $newname, $newinfo, $newinfoformat = FORMAT_HTML) { public function update_category($updateid, $newparent, $newname, $newinfo, $newinfoformat = FORMAT_HTML,
$idnumber = null) {
global $CFG, $DB; global $CFG, $DB;
if (empty($newname)) { if (empty($newname)) {
print_error('categorynamecantbeblank', 'question'); print_error('categorynamecantbeblank', 'question');
...@@ -480,6 +493,14 @@ class question_category_object { ...@@ -480,6 +493,14 @@ class question_category_object {
} }
} }
if (((string) $idnumber !== '') && !empty($tocontextid)) {
// While this check already exists in the form validation, this is a backstop preventing unnecessary errors.
if ($DB->record_exists('question_categories',
['idnumber' => $idnumber, 'contextid' => $tocontextid])) {
$idnumber = null;
}
}
// Update the category record. // Update the category record.
$cat = new stdClass(); $cat = new stdClass();
$cat->id = $updateid; $cat->id = $updateid;
...@@ -488,6 +509,9 @@ class question_category_object { ...@@ -488,6 +509,9 @@ class question_category_object {
$cat->infoformat = $newinfoformat; $cat->infoformat = $newinfoformat;
$cat->parent = $parentid; $cat->parent = $parentid;
$cat->contextid = $tocontextid; $cat->contextid = $tocontextid;
if ($idnumber) {
$cat->idnumber = $idnumber;
}
if ($newstamprequired) { if ($newstamprequired) {
$cat->stamp = make_unique_id_code(); $cat->stamp = make_unique_id_code();
} }
......
...@@ -63,6 +63,10 @@ class question_category_edit_form extends moodleform { ...@@ -63,6 +63,10 @@ class question_category_edit_form extends moodleform {
$mform->setDefault('info', ''); $mform->setDefault('info', '');
$mform->setType('info', PARAM_RAW); $mform->setType('info', PARAM_RAW);
$mform->addElement('text', 'idnumber', get_string('idnumber', 'question'), 'maxlength="100" size="10"');
$mform->addHelpButton('idnumber', 'idnumber', 'question');
$mform->setType('idnumber', PARAM_RAW);
$this->add_action_buttons(false, get_string('addcategory', 'question')); $this->add_action_buttons(false, get_string('addcategory', 'question'));
$mform->addElement('hidden', 'id', 0); $mform->addElement('hidden', 'id', 0);
...@@ -81,4 +85,33 @@ class question_category_edit_form extends moodleform { ...@@ -81,4 +85,33 @@ class question_category_edit_form extends moodleform {
} }
parent::set_data($current); parent::set_data($current);
} }
/**
* Validation.
*
* @param array $data
* @param array $files
* @return array the errors that were found
*/
public function validation($data, $files) {
global $DB;
$errors = parent::validation($data, $files);
// Add field validation check for duplicate idnumber.
list($parentid, $contextid) = explode(',', $data['parent']);
if (((string) $data['idnumber'] !== '') && !empty($contextid)) {
$conditions = 'contextid = ? AND idnumber = ?';
$params = [$contextid, $data['idnumber']];
if (!empty($data['id'])) {
$conditions .= ' AND id <> ?';
$params[] = $data['id'];
}
if ($DB->record_exists_select('question_categories', $conditions, $params)) {
$errors['idnumber'] = get_string('idnumbertaken', 'error');
}
}
return $errors;
}
} }
...@@ -170,6 +170,7 @@ class test_question_maker { ...@@ -170,6 +170,7 @@ class test_question_maker {
$q->id = 0; $q->id = 0;
$q->category = 0; $q->category = 0;
$q->idnumber = null;
$q->parent = 0; $q->parent = 0;
$q->questiontextformat = FORMAT_HTML; $q->questiontextformat = FORMAT_HTML;
$q->generalfeedbackformat = FORMAT_HTML; $q->generalfeedbackformat = FORMAT_HTML;
...@@ -190,6 +191,7 @@ class test_question_maker { ...@@ -190,6 +191,7 @@ class test_question_maker {
$qdata->id = 0; $qdata->id = 0;
$qdata->category = 0; $qdata->category = 0;
$qdata->idnumber = null;
$qdata->contextid = 0; $qdata->contextid = 0;
$qdata->parent = 0; $qdata->parent = 0;
$qdata->questiontextformat = FORMAT_HTML; $qdata->questiontextformat = FORMAT_HTML;
......
...@@ -406,6 +406,13 @@ class qformat_default { ...@@ -406,6 +406,13 @@ class qformat_default {
$question->timecreated = time(); $question->timecreated = time();
$question->modifiedby = $USER->id; $question->modifiedby = $USER->id;
$question->timemodified = time(); $question->timemodified = time();
if (isset($question->idnumber) && (string) $question->idnumber !== '') {
if ($DB->record_exists('question', ['idnumber' => $question->idnumber, 'category' => $question->category])) {
// We cannot have duplicate idnumbers in a category.
unset($question->idnumber);
}
}
$fileoptions = array( $fileoptions = array(
'subdirs' => true, 'subdirs' => true,
'maxfiles' => -1, 'maxfiles' => -1,
......
...@@ -236,6 +236,8 @@ class qformat_xml extends qformat_default { ...@@ -236,6 +236,8 @@ class qformat_xml extends qformat_default {
$qo->questiontext .= ' <img src="@@PLUGINFILE@@/' . $filename . '" />'; $qo->questiontext .= ' <img src="@@PLUGINFILE@@/' . $filename . '" />';
} }
$qo->idnumber = $this->getpath($question, ['#', 'idnumber', 0, '#'], null);
// Restore files in generalfeedback. // Restore files in generalfeedback.
$generalfeedback = $this->import_text_with_files($question, $generalfeedback = $this->import_text_with_files($question,
array('#', 'generalfeedback', 0), $qo->generalfeedback, $this->get_format($qo->questiontextformat)); array('#', 'generalfeedback', 0), $qo->generalfeedback, $this->get_format($qo->questiontextformat));
...@@ -1217,6 +1219,7 @@ class qformat_xml extends qformat_default { ...@@ -1217,6 +1219,7 @@ class qformat_xml extends qformat_default {
} }
$expout .= " <penalty>{$question->penalty}</penalty>\n"; $expout .= " <penalty>{$question->penalty}</penalty>\n";
$expout .= " <hidden>{$question->hidden}</hidden>\n"; $expout .= " <hidden>{$question->hidden}</hidden>\n";
$expout .= " <idnumber>{$question->idnumber}</idnumber>\n";
// The rest of the output depends on question type. // The rest of the output depends on question type.
switch($question->qtype) { switch($question->qtype) {
......
...@@ -48,6 +48,7 @@ class qformat_xml_test extends question_testcase { ...@@ -48,6 +48,7 @@ class qformat_xml_test extends question_testcase {
$q = new stdClass(); $q = new stdClass();
$q->id = 0; $q->id = 0;
$q->contextid = 0; $q->contextid = 0;
$q->idnumber = null;
$q->category = 0; $q->category = 0;
$q->parent = 0; $q->parent = 0;
$q->questiontextformat = FORMAT_HTML; $q->questiontextformat = FORMAT_HTML;
...@@ -342,6 +343,7 @@ END; ...@@ -342,6 +343,7 @@ END;
$qdata->length = 0; $qdata->length = 0;
$qdata->penalty = 0; $qdata->penalty = 0;
$qdata->hidden = 0; $qdata->hidden = 0;
$qdata->idnumber = null;
$exporter = new qformat_xml(); $exporter = new qformat_xml();
$xml = $exporter->writequestion($qdata); $xml = $exporter->writequestion($qdata);
...@@ -360,6 +362,7 @@ END; ...@@ -360,6 +362,7 @@ END;
<defaultgrade>0</defaultgrade> <defaultgrade>0</defaultgrade>
<penalty>0</penalty> <penalty>0</penalty>
<hidden>0</hidden> <hidden>0</hidden>
<idnumber></idnumber>
</question> </question>
'; ';
...@@ -487,6 +490,7 @@ END; ...@@ -487,6 +490,7 @@ END;
$qdata->length = 1; $qdata->length = 1;
$qdata->penalty = 0; $qdata->penalty = 0;
$qdata->hidden = 0; $qdata->hidden = 0;
$qdata->idnumber = null;
$qdata->options = new stdClass(); $qdata->options = new stdClass();
$qdata->options->id = 456; $qdata->options->id = 456;
$qdata->options->questionid = 123; $qdata->options->questionid = 123;
...@@ -516,6 +520,7 @@ END; ...@@ -516,6 +520,7 @@ END;
<defaultgrade>1</defaultgrade> <defaultgrade>1</defaultgrade>
<penalty>0</penalty> <penalty>0</penalty>
<hidden>0</hidden> <hidden>0</hidden>
<idnumber></idnumber>
<responseformat>monospaced</responseformat> <responseformat>monospaced</responseformat>
<responserequired>0</responserequired> <responserequired>0</responserequired>
<responsefieldlines>42</responsefieldlines> <responsefieldlines>42</responsefieldlines>
...@@ -649,6 +654,7 @@ END; ...@@ -649,6 +654,7 @@ END;
$qdata->length = 1; $qdata->length = 1;
$qdata->penalty = 0.3333333; $qdata->penalty = 0.3333333;
$qdata->hidden = 0; $qdata->hidden = 0;
$qdata->idnumber = null;
$qdata->options = new stdClass(); $qdata->options = new stdClass();
$qdata->options->shuffleanswers = 1; $qdata->options->shuffleanswers = 1;
...@@ -709,6 +715,7 @@ END; ...@@ -709,6 +715,7 @@ END;
<defaultgrade>1</defaultgrade> <defaultgrade>1</defaultgrade>
<penalty>0.3333333</penalty> <penalty>0.3333333</penalty>
<hidden>0</hidden> <hidden>0</hidden>
<idnumber></idnumber>
<shuffleanswers>true</shuffleanswers> <shuffleanswers>true</shuffleanswers>
<correctfeedback format="html"> <correctfeedback format="html">
<text>Well done.</text> <text>Well done.</text>
...@@ -880,6 +887,7 @@ END; ...@@ -880,6 +887,7 @@ END;
$qdata->length = 1; $qdata->length = 1;
$qdata->penalty = 0.3333333; $qdata->penalty = 0.3333333;
$qdata->hidden = 0; $qdata->hidden = 0;
$qdata->idnumber = null;
$qdata->options = new stdClass(); $qdata->options = new stdClass();
$qdata->options->single = 0; $qdata->options->single = 0;
...@@ -922,6 +930,7 @@ END; ...@@ -922,6 +930,7 @@ END;
<defaultgrade>2</defaultgrade> <defaultgrade>2</defaultgrade>
<penalty>0.3333333</penalty> <penalty>0.3333333</penalty>
<hidden>0</hidden> <hidden>0</hidden>
<idnumber></idnumber>
<single>false</single> <single>false</single>
<shuffleanswers>false</shuffleanswers> <shuffleanswers>false</shuffleanswers>
<answernumbering>abc</answernumbering> <answernumbering>abc</answernumbering>
...@@ -1053,6 +1062,7 @@ END; ...@@ -1053,6 +1062,7 @@ END;
$qdata->length = 1; $qdata->length = 1;
$qdata->penalty = 0.1; $qdata->penalty = 0.1;
$qdata->hidden = 0; $qdata->hidden = 0;
$qdata->idnumber = null;
$qdata->options = new stdClass(); $qdata->options = new stdClass();
$qdata->options->answers = array(