questions MDL-25104 and MDL-25088 fix question editing and import

Editing of some qtypes was broken since a previous commit by me earlier in the week.

Import of XML and GIFT should now work, but could use some more testing.
This commit is contained in:
Tim Hunt 2010-11-12 17:11:34 +00:00
parent f395cbddbd
commit 69988ed452
8 changed files with 309 additions and 427 deletions

View File

@ -448,8 +448,8 @@ class qformat_xml extends qformat_default {
$answers = $question['#']['answer'];
$a_count = 0;
foreach ($answers as $answer) {
$ans = $this->import_answer( $answer );
$qo->answer[$a_count] = $ans->answer;
$ans = $this->import_answer($answer);
$qo->answer[$a_count] = $ans->answer['text'];
$qo->fraction[$a_count] = $ans->fraction;
$qo->feedback[$a_count] = $ans->feedback;
++$a_count;
@ -494,7 +494,7 @@ class qformat_xml extends qformat_default {
foreach ($answers as $answer) {
// answer outside of <text> is deprecated
$obj = $this->import_answer($answer);
$qo->answer[] = $obj->answer;
$qo->answer[] = $obj->answer['text'];
if (empty($qo->answer)) {
$qo->answer = '*';
}
@ -520,6 +520,8 @@ class qformat_xml extends qformat_default {
$qo->unitpenalty = $this->getpath( $question, array('#','unitpenalty',0,'#'), 0 );
$qo->showunits = $this->getpath( $question, array('#','showunits',0,'#'), 0 );
$qo->unitsleft = $this->getpath( $question, array('#','unitsleft',0,'#'), 0 );
$qo->instructions['text'] = '';
$qo->instructions['format'] = FORMAT_HTML;
$instructions = $this->getpath($question, array('#', 'instructions'), array());
if (!empty($instructions)) {
$qo->instructions = array();

View File

@ -37,37 +37,28 @@ class question_essay_qtype extends default_questiontype {
function save_question_options($question) {
global $DB;
$context = $question->context;
$result = true;
$update = true;
$answer = $DB->get_record("question_answers", array("question" => $question->id));
$answer = $DB->get_record('question_answers', array('question' => $question->id));
if (!$answer) {
$answer = new stdClass;
$answer->question = $question->id;
$update = false;
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
$answer->feedback = $question->feedback['text'];
$answer->feedbackformat = $question->feedback['format'];
$answer->answer = $answer->feedback;
$answer->answerformat = $question->feedback['format'];
$answer->fraction = $question->fraction;
if ($update) {
$answer->feedback = file_save_draft_area_files($question->feedback['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback['text']));
$answer->answer = $answer->feedback;
$DB->update_record("question_answers", $answer);
} else {
$answer->feedback = $question->feedback['text'];
$answer->answer = $answer->feedback;
$answer->id = $DB->insert_record('question_answers', $answer);
if (isset($question->feedback['files'])) {
// import
foreach ($question->feedback['files'] as $file) {
$this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
}
} else {
$answer->feedback = file_save_draft_area_files($question->feedback['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback['text']));
}
$answer->answer = $answer->feedback;
$DB->update_record('question_answers', $answer);
}
return $result;
$answer->feedback = $this->import_or_save_files($question->feedback,
$context, 'question', 'answerfeedback', $answer->id);
$answer->answer = $answer->feedback;
$DB->update_record('question_answers', $answer);
return true;
}
function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {

View File

@ -42,73 +42,63 @@ class question_match_qtype extends default_questiontype {
$context = $question->context;
$result = new stdClass;
if (!$oldsubquestions = $DB->get_records("question_match_sub", array("question" => $question->id), "id ASC")) {
$oldsubquestions = array();
}
$oldsubquestions = $DB->get_records('question_match_sub',
array('question' => $question->id), 'id ASC');
// $subquestions will be an array with subquestion ids
$subquestions = array();
// Insert all the new question+answer pairs
foreach ($question->subquestions as $key => $questiontext) {
if (!empty($questiontext['itemid'])) {
$itemid = $questiontext['itemid'];
if ($questiontext['text'] == '' && trim($question->subanswers[$key]) == '') {
continue;
}
$files = $questiontext['files'];
$format = $questiontext['format'];
$questiontext = trim($questiontext['text']);
$answertext = trim($question->subanswers[$key]);
if ($questiontext != '' || $answertext != '') {
if ($subquestion = array_shift($oldsubquestions)) { // Existing answer, so reuse it
$subquestion->answertext = $answertext;
$subquestion->questiontext = file_save_draft_area_files($itemid, $context->id, 'qtype_match', 'subquestion', $subquestion->id, self::$fileoptions, $questiontext);
$subquestion->questiontextformat = $format;
$DB->update_record("question_match_sub", $subquestion);
} else {
$subquestion = new stdClass;
// Determine a unique random code
$subquestion->code = rand(1, 999999999);
while ($DB->record_exists('question_match_sub', array('code' => $subquestion->code, 'question' => $question->id))) {
$subquestion->code = rand();
}
$subquestion->question = $question->id;
$subquestion->questiontext = $questiontext;
$subquestion->questiontextformat = $format;
$subquestion->answertext = $answertext;
$subquestion->id = $DB->insert_record("question_match_sub", $subquestion);
if (!isset($itemid)) {
foreach ($files as $file) {
$this->import_file($context, 'qtype_match', 'subquestion', $subquestion->id, $file);
}
} else {
$questiontext = file_save_draft_area_files($itemid, $context->id, 'qtype_match', 'subquestion', $subquestion->id, self::$fileoptions, $questiontext);
}
$DB->set_field('question_match_sub', 'questiontext', $questiontext, array('id'=>$subquestion->id));
}
$subquestions[] = $subquestion->id;
}
if ($questiontext != '' && $answertext == '') {
if ($questiontext['text'] != '' && trim($question->subanswers[$key]) == '') {
$result->notice = get_string('nomatchinganswer', 'quiz', $questiontext);
}
}
// delete old subquestions records
if (!empty($oldsubquestions)) {
foreach($oldsubquestions as $os) {
$DB->delete_records('question_match_sub', array('id' => $os->id));
// Update an existing subquestion if possible.
$subquestion = array_shift($oldsubquestions);
if (!$subquestion) {
$subquestion = new stdClass;
// Determine a unique random code
$subquestion->code = rand(1, 999999999);
while ($DB->record_exists('question_match_sub', array('code' => $subquestion->code, 'question' => $question->id))) {
$subquestion->code = rand(1, 999999999);
}
$subquestion->question = $question->id;
$subquestion->questiontext = '';
$subquestion->answertext = '';
$subquestion->id = $DB->insert_record('question_match_sub', $subquestion);
}
$subquestion->questiontext = $this->import_or_save_files($questiontext,
$context, 'qtype_match', 'subquestion', $subquestion->id);
$subquestion->questiontextformat = $questiontext['format'];
$subquestion->answertext = trim($question->subanswers[$key]);
$DB->update_record('question_match_sub', $subquestion);
$subquestions[] = $subquestion->id;
}
if ($options = $DB->get_record("question_match", array("question" => $question->id))) {
$options->subquestions = implode(",",$subquestions);
// Delete old subquestions records
$fs = get_file_storage();
foreach($oldsubquestions as $oldsub) {
$fs->delete_area_files($context->id, 'qtype_match', 'subquestion', $oldsub->id);
$DB->delete_records('question_match_sub', array('id' => $oldsub->id));
}
if ($options = $DB->get_record('question_match', array('question' => $question->id))) {
$options->subquestions = implode(',', $subquestions);
$options->shuffleanswers = $question->shuffleanswers;
$DB->update_record("question_match", $options);
$DB->update_record('question_match', $options);
} else {
unset($options);
$options->question = $question->id;
$options->subquestions = implode(",",$subquestions);
$options->subquestions = implode(',', $subquestions);
$options->shuffleanswers = $question->shuffleanswers;
$DB->insert_record("question_match", $options);
$DB->insert_record('question_match', $options);
}
if (!empty($result->notice)) {

View File

@ -36,135 +36,109 @@ class question_multichoice_qtype extends default_questiontype {
global $DB;
$context = $question->context;
$result = new stdClass;
if (!$oldanswers = $DB->get_records("question_answers", array("question" => $question->id), "id ASC")) {
$oldanswers = array();
}
$oldanswers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC');
// following hack to check at least two answers exist
$answercount = 0;
foreach ($question->answer as $key=>$dataanswer) {
if ($dataanswer != "") {
foreach ($question->answer as $key => $answer) {
if ($answer != '') {
$answercount++;
}
}
$answercount += count($oldanswers);
if ($answercount < 2) { // check there are at lest 2 answers for multiple choice
$result->notice = get_string("notenoughanswers", "qtype_multichoice", "2");
$result->notice = get_string('notenoughanswers', 'qtype_multichoice', '2');
return $result;
}
// Insert all the new answers
$totalfraction = 0;
$maxfraction = -1;
$answers = array();
foreach ($question->answer as $key => $answerdata) {
if ($answerdata == '') {
continue;
}
foreach ($question->answer as $key => $dataanswer) {
if ($dataanswer != "") {
$feedbackformat = $question->feedback[$key]['format'];
if ($answer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer->answer = $dataanswer;
$answer->fraction = $question->fraction[$key];
$answer->feedbackformat = $feedbackformat;
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
$DB->update_record("question_answers", $answer);
} else {
// import goes here too
unset($answer);
if (is_array($dataanswer)) {
$answer->answer = $dataanswer['text'];
$answer->answerformat = $dataanswer['format'];
} else {
$answer->answer = $dataanswer;
}
$answer->question = $question->id;
$answer->fraction = $question->fraction[$key];
$answer->feedback = $question->feedback[$key]['text'];
$answer->feedbackformat = $feedbackformat;
$answer->id = $DB->insert_record("question_answers", $answer);
if (isset($question->feedback[$key]['files'])) {
foreach ($question->feedback[$key]['files'] as $file) {
$this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
}
} else {
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
}
// Update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
$DB->set_field('question_answers', 'feedback', $answer->feedback, array('id'=>$answer->id));
}
$answers[] = $answer->id;
$answer->answer = $answerdata;
$answer->answer = FORMAT_HTML;
$answer->fraction = $question->fraction[$key];
$answer->feedback = $this->import_or_save_files($question->feedback[$key],
$context, 'question', 'answerfeedback', $answer->id);
$answer->feedbackformat = $question->feedback[$key]['format'];
if ($question->fraction[$key] > 0) { // Sanity checks
$totalfraction += $question->fraction[$key];
}
if ($question->fraction[$key] > $maxfraction) {
$maxfraction = $question->fraction[$key];
}
$DB->update_record('question_answers', $answer);
$answers[] = $answer->id;
if ($question->fraction[$key] > 0) {
$totalfraction += $question->fraction[$key];
}
if ($question->fraction[$key] > $maxfraction) {
$maxfraction = $question->fraction[$key];
}
}
$update = true;
$options = $DB->get_record("question_multichoice", array("question" => $question->id));
// Delete any left over old answer records.
$fs = get_file_storage();
foreach($oldanswers as $oldanswer) {
$fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
$DB->delete_records('question_answers', array('id' => $oldanswer->id));
}
$options = $DB->get_record('question_multichoice', array('question' => $question->id));
if (!$options) {
$update = false;
$options = new stdClass;
$options->question = $question->id;
$options->correctfeedback = '';
$options->partiallycorrectfeedback = '';
$options->incorrectfeedback = '';
$options->id = $DB->insert_record('question_multichoice', $options);
}
$options->answers = implode(",",$answers);
$options->answers = implode(',', $answers);
$options->single = $question->single;
if(isset($question->layout)){
if (isset($question->layout)) {
$options->layout = $question->layout;
}
$options->answernumbering = $question->answernumbering;
$options->shuffleanswers = $question->shuffleanswers;
$options->correctfeedback = $this->import_or_save_files($question->correctfeedback,
$context, 'qtype_multichoice', 'correctfeedback', $question->id);
$options->correctfeedbackformat = $question->correctfeedback['format'];
$options->partiallycorrectfeedback = $this->import_or_save_files($question->correctfeedback,
$context, 'qtype_multichoice', 'partiallycorrectfeedback', $question->id);
$options->partiallycorrectfeedbackformat = $question->partiallycorrectfeedback['format'];
$options->incorrectfeedback = $this->import_or_save_files($question->correctfeedback,
$context, 'qtype_multichoice', 'incorrectfeedback', $question->id);
$options->incorrectfeedbackformat = $question->incorrectfeedback['format'];
foreach (array('correct', 'partiallycorrect', 'incorrect') as $feedbacktype) {
$feedbackname = $feedbacktype . 'feedback';
$feedback = $question->$feedbackname;
$feedbackformatname = $feedbackname . 'format';
$options->$feedbackname = trim($feedback['text']);
$options->$feedbackformatname = trim($feedback['format']);
if (isset($feedback['files'])) {
// import
foreach ($feedback['files'] as $file) {
$this->import_file($context, 'qtype_multichoice', $feedbackname, $question->id, $file);
}
} else {
$options->$feedbackname = file_save_draft_area_files(
$feedback['itemid'], $context->id, 'qtype_multichoice', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
}
}
if ($update) {
$DB->update_record('question_multichoice', $options);
} else {
$DB->insert_record('question_multichoice', $options);
}
// delete old answer records
if (!empty($oldanswers)) {
foreach($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
}
$DB->update_record('question_multichoice', $options);
/// Perform sanity checks on fractional grades
if ($options->single) {
if ($maxfraction != 1) {
$maxfraction = $maxfraction * 100;
$result->noticeyesno = get_string("fractionsnomax", "qtype_multichoice", $maxfraction);
$result->noticeyesno = get_string('fractionsnomax', 'qtype_multichoice', $maxfraction * 100);
return $result;
}
} else {
$totalfraction = round($totalfraction,2);
$totalfraction = round($totalfraction, 2);
if ($totalfraction != 1) {
$totalfraction = $totalfraction * 100;
$result->noticeyesno = get_string("fractionsaddwrong", "qtype_multichoice", $totalfraction);
$result->noticeyesno = get_string('fractionsaddwrong', 'qtype_multichoice', $totalfraction * 100);
return $result;
}
}
return true;
}

View File

@ -149,78 +149,58 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$context = $question->context;
// Get old versions of the objects
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
if (!$oldoptions = $DB->get_records('question_numerical', array('question' => $question->id), 'answer ASC')) {
$oldoptions = array();
}
$oldanswers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC');
$oldoptions = $DB->get_records('question_numerical',
array('question' => $question->id), 'answer ASC');
// Save the units.
$result = $this->save_numerical_units($question);
if (isset($result->error)) {
return $result;
} else {
$units = &$result->units;
$units = $result->units;
}
// Insert all the new answers
foreach ($question->answer as $key => $dataanswer) {
if (is_array($dataanswer)) {
$dataanswer = $dataanswer['text'];
}
foreach ($question->answer as $key => $answerdata) {
// Check for, and ingore, completely blank answer from the form.
if (trim($dataanswer) == '' && $question->fraction[$key] == 0 &&
if (trim($answerdata) == '' && $question->fraction[$key] == 0 &&
html_is_blank($question->feedback[$key]['text'])) {
continue;
}
$answer = new stdClass;
$answer->question = $question->id;
if (trim($dataanswer) === '*') {
// Update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
if (trim($answerdata) === '*') {
$answer->answer = '*';
} else {
$answer->answer = $this->apply_unit($dataanswer, $units);
$answer->answer = $this->apply_unit($answerdata, $units);
if ($answer->answer === false) {
$result->notice = get_string('invalidnumericanswer', 'quiz');
}
}
$answer->fraction = $question->fraction[$key];
$feedbacktext = trim($question->feedback[$key]['text']);
$answer->feedback = $this->import_or_save_files($question->feedback[$key],
$context, 'question', 'answerfeedback', $answer->id);
$answer->feedbackformat = $question->feedback[$key]['format'];
if (!empty($question->feedback[$key]['itemid'])) {
$draftid = $question->feedback[$key]['itemid'];
} else {
$draftid = '' ;
}
$feedbackfiles = $question->feedback[$key]['files'];
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$feedbacktext = file_save_draft_area_files($draftid, $context->id, 'question', 'answerfeedback', $oldanswer->id, self::$fileoptions, $feedbacktext);
$answer->feedback = $feedbacktext;
$answer->id = $oldanswer->id;
$DB->update_record("question_answers", $answer);
} else { // This is a completely new answer
$answer->feedback = $feedbacktext;
$answer->id = $DB->insert_record("question_answers", $answer);
if ($draftid) {
$feedbacktext = file_save_draft_area_files($draftid, $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $feedbacktext);
} else {
foreach ($feedbackfiles as $file) {
$this->import_file($question->context, 'question', 'answerfeedback', $answer->id, $file);
}
}
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$answer->id));
}
$DB->update_record('question_answers', $answer);
// Set up the options object
$options = array_shift($oldoptions);
if (!$options = array_shift($oldoptions)) {
$options = new stdClass;
$options = new stdClass();
}
$options->question = $question->id;
$options->answer = $answer->id;
$options->question = $question->id;
$options->answer = $answer->id;
if (trim($question->tolerance[$key]) == '') {
$options->tolerance = '';
} else {
@ -229,35 +209,28 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$result->notice = get_string('invalidnumerictolerance', 'quiz');
}
}
// Save options
if (isset($options->id)) { // reusing existing record
if (isset($options->id)) {
$DB->update_record('question_numerical', $options);
} else { // new options
} else {
$DB->insert_record('question_numerical', $options);
}
}
// delete old answer records
if (!empty($oldanswers)) {
foreach($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
// Delete any left over old answer records.
$fs = get_file_storage();
foreach($oldanswers as $oldanswer) {
$fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
$DB->delete_records('question_answers', array('id' => $oldanswer->id));
}
foreach($oldoptions as $oldoption) {
$DB->delete_records('question_numerical', array('id' => $oldoption->id));
}
// delete old answer records
if (!empty($oldoptions)) {
foreach($oldoptions as $oo) {
$DB->delete_records('question_numerical', array('id' => $oo->id));
}
}
$result = $this->save_numerical_options($question);
if (isset($result->error)) {
return $result;
}
// Report any problems.
if (!empty($result->notice)) {
if (!empty($result->error) || !empty($result->notice)) {
return $result;
}
return true;
}
@ -269,31 +242,32 @@ class question_numerical_qtype extends question_shortanswer_qtype {
* as old question.
*
*/
function save_numerical_options(&$question) {
function save_numerical_options($question) {
global $DB;
// echo"<p> ".$question->id."question<pre>";print_r($question) ;echo"</pre></p>";
$result = new stdClass;
// numerical options
$update = true ;
$options = $DB->get_record('question_numerical_options', array('question' => $question->id));
if (!$options) {
$update = false;
$options = new stdClass;
$options->question = $question->id;
$options->instructions = '';
$options->id = $DB->insert_record('question_numerical_options', $options);
}
if(isset($question->options->unitgradingtype)){
if (isset($question->options->unitgradingtype)) {
$options->unitgradingtype = $question->options->unitgradingtype;
}else {
} else {
$options->unitgradingtype = 0 ;
}
if(isset($question->unitpenalty)){
if (isset($question->unitpenalty)){
$options->unitpenalty = $question->unitpenalty;
}else { //so this is either an old question or a close question type
} else { //so this is either an old question or a close question type
$options->unitpenalty = 1 ;
}
// if we came from the form then 'unitrole' exists
if(isset($question->unitrole)){
if (isset($question->unitrole)){
switch ($question->unitrole){
case '0' : $options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
break ;
@ -307,58 +281,30 @@ class question_numerical_qtype extends question_shortanswer_qtype {
break ;
}
} else {
if(isset($question->showunits)){
if (isset($question->showunits)){
$options->showunits = $question->showunits;
}else {
} else {
if ($defaultunit = $this->get_default_numerical_unit($question)) {
// so units can be used
$options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
}else {
} else {
// only numerical will be graded
$options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
}
}
}
if(isset($question->unitsleft)){
if (isset($question->unitsleft)) {
$options->unitsleft = $question->unitsleft;
}else {
} else {
$options->unitsleft = 0 ;
}
$options->instructionsformat = '1' ;
if ( isset($question->instructions) && isset($question->instructions['format']) && $question->instructions['format'] != '' ){
$options->instructionsformat = $question->instructions['format'];
}
if(isset($question->instructions) && isset($question->instructions['text']) ){
$options->instructions = trim($question->instructions['text']);
}else {
$options->instructions = '' ;
}
$component = 'qtype_' . $question->qtype;
if (isset($question->instructionsfiles) && is_array($question->instructionsfiles)) {
// import
foreach ($question->instructionsfiles as $file) {
$this->import_file($question->context, $component, 'instruction', $question->id, $file);
}
} else {
if(isset($question->instructions)){
$options->instructions = file_save_draft_area_files($question->instructions['itemid'],
$question->context->id, // context
$component, // component
'instruction', // filearea
$question->id, // itemid
self::$fileoptions, // options
$question->instructions['text'] // text
);
}else {
$options->instructions = "";
}
}
if ($update) {
$DB->update_record("question_numerical_options", $options);
} else {
$id = $DB->insert_record("question_numerical_options", $options);
}
$options->instructions = $this->import_or_save_files($question->instructions,
$question->context, 'qtype_' . $question->qtype, 'instructions', $options->id);
$options->instructionsformat = $question->instructions['format'];
$DB->update_record('question_numerical_options', $options);
return $result;
}
@ -487,7 +433,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$nameprefix = $question->name_prefix;
$component = 'qtype_' . $question->qtype;
// rewrite instructions text
$question->options->instructions = quiz_rewrite_question_urls($question->options->instructions, 'pluginfile.php', $context->id, $component, 'instruction', array($state->attempt, $state->question), $question->id);
$question->options->instructions = quiz_rewrite_question_urls($question->options->instructions, 'pluginfile.php', $context->id, $component, 'instructions', array($state->attempt, $state->question), $question->id);
/// Print question text and media

View File

@ -46,7 +46,11 @@ require_once($CFG->libdir . '/questionlib.php');
* @subpackage questiontypes
*/
class default_questiontype {
public static $fileoptions = array('subdirs'=>false, 'maxfiles'=>-1, 'maxbytes'=>0);
protected $fileoptions = array(
'subdirs' => false,
'maxfiles' => -1,
'maxbytes' => 0,
);
/**
* Name of the question type
@ -361,10 +365,10 @@ class default_questiontype {
$question->timemodified = time();
if (!empty($question->questiontext)) {
$question->questiontext = file_save_draft_area_files($form->questiontext['itemid'], $context->id, 'question', 'questiontext', (int)$question->id, self::$fileoptions, $question->questiontext);
$question->questiontext = file_save_draft_area_files($form->questiontext['itemid'], $context->id, 'question', 'questiontext', (int)$question->id, $this->fileoptions, $question->questiontext);
}
if (!empty($question->generalfeedback)) {
$question->generalfeedback = file_save_draft_area_files($form->generalfeedback['itemid'], $context->id, 'question', 'generalfeedback', (int)$question->id, self::$fileoptions, $question->generalfeedback);
$question->generalfeedback = file_save_draft_area_files($form->generalfeedback['itemid'], $context->id, 'question', 'generalfeedback', (int)$question->id, $this->fileoptions, $question->generalfeedback);
}
$DB->update_record('question', $question);
@ -1653,6 +1657,35 @@ class default_questiontype {
return $context;
}
/**
* Save the file belonging to one text field.
*
* @param array $field the data from the form (or from import). This will
* normally have come from the formslib editor element, so it will be an
* array with keys 'text', 'format' and 'itemid'. However, when we are
* importing, it will be an array with keys 'text', 'format' and 'files'
* @param object $context the context the question is in.
* @param string $component indentifies the file area.
* @param string $filearea indentifies the file area.
* @param integer $itemid identifies the file area.
*
* @return string the text for this field, after files have been processed.
*/
protected function import_or_save_files($field, $context, $component, $filearea, $itemid) {
if (!empty($field['itemid'])) {
// This is the normal case. We are safing the questions editing form.
return file_save_draft_area_files($field['itemid'], $context->id, $component,
$filearea, $itemid, $this->fileoptions, trim($field['text']));
} else if (!empty($field['files'])) {
// This is the case when we are doing an import.
foreach ($question->feedback['files'] as $file) {
$this->import_file($context, 'question', 'answerfeedback', $itemid, $file);
}
}
return trim($field['text']);
}
/**
* Move all the files belonging to this question from one context to another.
* @param integer $questionid the question being moved.

View File

@ -65,88 +65,63 @@ class question_shortanswer_qtype extends default_questiontype {
$context = $question->context;
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
$answers = array();
$maxfraction = -1;
$oldanswers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC');
// Insert all the new answers
foreach ($question->answer as $key => $dataanswer) {
if (is_array($dataanswer)) {
$dataanswer = $dataanswer['text'];
}
// Check for, and ingore, completely blank answer from the form.
if (trim($dataanswer) == '' && $question->fraction[$key] == 0 &&
$answers = array();
$maxfraction = -1;
foreach ($question->answer as $key => $answerdata) {
// Check for, and ignore, completely blank answer from the form.
if (trim($answerdata) == '' && $question->fraction[$key] == 0 &&
html_is_blank($question->feedback[$key]['text'])) {
continue;
}
$feedbackformat = $question->feedback[$key]['format'];
if (isset($question->feedback[$key]['files'])) {
$feedbackfiles = $question->feedback[$key]['files'];
}
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer = $oldanswer;
$answer->answer = trim($dataanswer);
$answer->fraction = $question->fraction[$key];
// save draft file and rewrite text in feedback
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $oldanswer->id, self::$fileoptions, $question->feedback[$key]['text']);
$answer->feedbackformat = $feedbackformat;
$DB->update_record("question_answers", $answer);
} else { // This is a completely new answer
$answer = new stdClass;
$answer->answer = trim($dataanswer);
// Update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->fraction = $question->fraction[$key];
// feedback content needs to be rewriten
$answer->feedback = $question->feedback[$key]['text'];
$answer->feedbackformat = $feedbackformat;
$answer->id = $DB->insert_record("question_answers", $answer);
if (isset($feedbackfiles)) {
// import
foreach ($feedbackfiles as $file) {
$this->import_file($question->context, 'question', 'answerfeedback', $answer->id, $file);
}
} else {
// save draft file and rewrite text in feedback
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
}
// update feedback content
$DB->set_field('question_answers', 'feedback', $answer->feedback, array('id'=>$answer->id));
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
$answer->answer = trim($answerdata);
$answer->fraction = $question->fraction[$key];
$answer->feedback = $this->import_or_save_files($question->feedback[$key],
$context, 'question', 'answerfeedback', $answer->id);
$answer->feedbackformat = $question->feedback[$key]['format'];
$DB->update_record('question_answers', $answer);
$answers[] = $answer->id;
if ($question->fraction[$key] > $maxfraction) {
$maxfraction = $question->fraction[$key];
}
}
// Delete any left over old answer records.
$fs = get_file_storage();
foreach($oldanswers as $oldanswer) {
$fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
$DB->delete_records('question_answers', array('id' => $oldanswer->id));
}
$question->answers = implode(',', $answers);
$parentresult = parent::save_question_options($question);
if($parentresult !== null) { // Parent function returns null if all is OK
if ($parentresult !== null) {
// Parent function returns null if all is OK
return $parentresult;
}
// delete old answer records
if (!empty($oldanswers)) {
foreach($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
// Perform sanity checks on fractional grades
if ($maxfraction != 1) {
$result->noticeyesno = get_string('fractionsnomax', 'quiz', $maxfraction * 100);
return $result;
}
/// Perform sanity checks on fractional grades
if ($maxfraction != 1) {
$maxfraction = $maxfraction * 100;
$result->noticeyesno = get_string("fractionsnomax", "quiz", $maxfraction);
return $result;
} else {
return true;
}
return true;
}
function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {

View File

@ -35,99 +35,70 @@ class question_truefalse_qtype extends default_questiontype {
function save_question_options($question) {
global $DB;
$result = new stdClass;
$context = $question->context;
// Fetch old answer ids so that we can reuse them
$oldanswers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC');
// Save the true answer - update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
$answer->answer = get_string('true', 'quiz');
$answer->fraction = $question->correctanswer;
$answer->feedback = $this->import_or_save_files($question->feedbacktrue,
$context, 'question', 'answerfeedback', $answer->id);
$answer->feedbackformat = $question->feedbacktrue['format'];
$DB->update_record('question_answers', $answer);
$trueid = $answer->id;
// Save the false answer - update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
$answer->answer = get_string('false', 'quiz');
$answer->fraction = 1 - (int)$question->correctanswer;
$answer->feedback = $this->import_or_save_files($question->feedbackfalse,
$context, 'question', 'answerfeedback', $answer->id);
$answer->feedbackformat = $question->feedbackfalse['format'];
$DB->update_record('question_answers', $answer);
$falseid = $answer->id;
// Delete any left over old answer records.
$fs = get_file_storage();
// fetch old answer ids so that we can reuse them
if (!$oldanswers = $DB->get_records("question_answers", array("question" => $question->id), "id ASC")) {
$oldanswers = array();
}
$feedbacktext = $question->feedbacktrue['text'];
$feedbackitemid = $question->feedbacktrue['itemid'];
$feedbackformat = $question->feedbacktrue['format'];
if (isset($question->feedbacktruefiles)) {
$files = $question->feedbacktruefiles;
}
// Save answer 'True'
if ($true = array_shift($oldanswers)) { // Existing answer, so reuse it
$true->answer = get_string("true", "quiz");
$true->fraction = $question->correctanswer;
$true->feedback = $question->feedbacktrue;
$true->feedback = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $true->id, self::$fileoptions, $feedbacktext);
$true->feedbackformat = $feedbackformat;
$DB->update_record("question_answers", $true);
} else {
unset($true);
$true = new stdClass();
$true->answer = get_string("true", "quiz");
$true->question = $question->id;
$true->fraction = $question->correctanswer;
$true->feedback = '';
$true->feedbackformat = $feedbackformat;
$true->id = $DB->insert_record("question_answers", $true);
// import
if (isset($files)) {
foreach ($files as $file) {
$this->import_file($question->context, 'question', 'answerfeedback', $true->id, $file);
}
} else {
// moodle form
$feedbacktext = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $true->id, self::$fileoptions, $feedbacktext);
}
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$true->id));
}
$feedbacktext = $question->feedbackfalse['text'];
$feedbackitemid = $question->feedbackfalse['itemid'];
$feedbackformat = $question->feedbackfalse['format'];
// Save answer 'False'
if ($false = array_shift($oldanswers)) { // Existing answer, so reuse it
$false->answer = get_string("false", "quiz");
$false->fraction = 1 - (int)$question->correctanswer;
$false->feedback = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $false->id, self::$fileoptions, $feedbacktext);
$false->feedbackformat = $feedbackformat;
$DB->update_record("question_answers", $false);
} else {
unset($false);
$false = new stdClass();
$false->answer = get_string("false", "quiz");
$false->question = $question->id;
$false->fraction = 1 - (int)$question->correctanswer;
$false->feedback = '';
$false->feedbackformat = $feedbackformat;
$false->id = $DB->insert_record("question_answers", $false);
if ($feedbackitemid == null && !empty($files)) {
foreach ($files as $file) {
$this->import_file($question->context, 'question', 'answerfeedback', $false->id, $file);
}
} else {
$feedbacktext = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $false->id, self::$fileoptions, $feedbacktext);
}
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$false->id));
}
// delete any leftover old answer records (there couldn't really be any, but who knows)
if (!empty($oldanswers)) {
foreach($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
foreach($oldanswers as $oldanswer) {
$fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
$DB->delete_records('question_answers', array('id' => $oldanswer->id));
}
// Save question options in question_truefalse table
if ($options = $DB->get_record("question_truefalse", array("question" => $question->id))) {
if ($options = $DB->get_record('question_truefalse', array('question' => $question->id))) {
// No need to do anything, since the answer IDs won't have changed
// But we'll do it anyway, just for robustness
$options->trueanswer = $true->id;
$options->falseanswer = $false->id;
$DB->update_record("question_truefalse", $options);
$options->trueanswer = $trueid;
$options->falseanswer = $falseid;
$DB->update_record('question_truefalse', $options);
} else {
unset($options);
$options = new stdClass();
$options->question = $question->id;
$options->trueanswer = $true->id;
$options->falseanswer = $false->id;
$DB->insert_record("question_truefalse", $options);
$options->trueanswer = $trueid;
$options->falseanswer = $falseid;
$DB->insert_record('question_truefalse', $options);
}
return true;
}