public function save_question_options($question) { global $DB; $result = new stdClass(); $context = $question->context; $oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC'); $maxfraction = -1; // Insert all the new answers. 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; } // 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 = 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); if ($question->fraction[$key] > $maxfraction) { $maxfraction = $question->fraction[$key]; } } $parentresult = parent::save_question_options($question); if ($parentresult !== null) { // Parent function returns null if all is OK. return $parentresult; } // 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)); } $this->save_hints($question); // Perform sanity checks on fractional grades. if ($maxfraction != 1) { $result->noticeyesno = get_string('fractionsnomax', 'question', $maxfraction * 100); return $result; } }
public function save_question_options($question) { global $DB; $result = new stdClass(); $context = $question->context; $question->feedbackperconditions = rtrim(str_replace("\r\n", "\n", $question->feedbackperconditions), "\n"); $question->conditions = rtrim(str_replace("\r\n", "\n", $question->conditions), "\n"); $parentresult = parent::save_question_options($question); if ($parentresult !== null) { // Parent function returns null if all is OK return $parentresult; } $this->save_hints($question); return $parentresult; }
public function save_question_options($question) { global $DB; $result = new stdClass(); // Perform sanity checks on fractional grades. $maxfraction = -1; foreach ($question->answer as $key => $answerdata) { if ($question->fraction[$key] > $maxfraction) { $maxfraction = $question->fraction[$key]; } } if ($maxfraction != 1) { $result->error = get_string('fractionsnomax', 'question', $maxfraction * 100); return $result; } parent::save_question_options($question); $this->save_question_answers($question); $this->save_hints($question); }
public function save_question_options($fromform) { global $DB; $context = $fromform->context; parent::save_question_options($fromform); $options = $DB->get_record('qtype_stack_options', array('questionid' => $fromform->id)); if (!$options) { $options = new stdClass(); $options->questionid = $fromform->id; $options->questionvariables = ''; $options->specificfeedback = ''; $options->prtcorrect = ''; $options->prtpartiallycorrect = ''; $options->prtincorrect = ''; $options->id = $DB->insert_record('qtype_stack_options', $options); } $options->questionvariables = $fromform->questionvariables; $options->specificfeedback = $this->import_or_save_files($fromform->specificfeedback, $context, 'qtype_stack', 'specificfeedback', $fromform->id); $options->specificfeedbackformat = $fromform->specificfeedback['format']; $options->questionnote = $fromform->questionnote; $options->questionsimplify = $fromform->questionsimplify; $options->assumepositive = $fromform->assumepositive; $options->prtcorrect = $this->import_or_save_files($fromform->prtcorrect, $context, 'qtype_stack', 'prtcorrect', $fromform->id); $options->prtcorrectformat = $fromform->prtcorrect['format']; $options->prtpartiallycorrect = $this->import_or_save_files($fromform->prtpartiallycorrect, $context, 'qtype_stack', 'prtpartiallycorrect', $fromform->id); $options->prtpartiallycorrectformat = $fromform->prtpartiallycorrect['format']; $options->prtincorrect = $this->import_or_save_files($fromform->prtincorrect, $context, 'qtype_stack', 'prtincorrect', $fromform->id); $options->prtincorrectformat = $fromform->prtincorrect['format']; $options->multiplicationsign = $fromform->multiplicationsign; $options->sqrtsign = $fromform->sqrtsign; $options->complexno = $fromform->complexno; $options->inversetrig = $fromform->inversetrig; $options->matrixparens = $fromform->matrixparens; $options->variantsselectionseed = $fromform->variantsselectionseed; $DB->update_record('qtype_stack_options', $options); $inputnames = stack_utils::extract_placeholders($fromform->questiontext, 'input'); $inputs = $DB->get_records('qtype_stack_inputs', array('questionid' => $fromform->id), '', 'name, id, questionid'); $questionhasinputs = false; foreach ($inputnames as $inputname) { if (array_key_exists($inputname, $inputs)) { $input = $inputs[$inputname]; unset($inputs[$inputname]); } else { $input = new stdClass(); $input->questionid = $fromform->id; $input->name = $inputname; $input->options = ''; $input->id = $DB->insert_record('qtype_stack_inputs', $input); } $input->type = $fromform->{$inputname . 'type'}; $input->tans = $fromform->{$inputname . 'modelans'}; $input->boxsize = $fromform->{$inputname . 'boxsize'}; $input->strictsyntax = $fromform->{$inputname . 'strictsyntax'}; $input->insertstars = $fromform->{$inputname . 'insertstars'}; $input->syntaxhint = $fromform->{$inputname . 'syntaxhint'}; $input->forbidwords = $fromform->{$inputname . 'forbidwords'}; $input->allowwords = $fromform->{$inputname . 'allowwords'}; $input->forbidfloat = $fromform->{$inputname . 'forbidfloat'}; $input->requirelowestterms = $fromform->{$inputname . 'requirelowestterms'}; $input->checkanswertype = $fromform->{$inputname . 'checkanswertype'}; $input->mustverify = $fromform->{$inputname . 'mustverify'}; $input->showvalidation = $fromform->{$inputname . 'showvalidation'}; $input->options = $fromform->{$inputname . 'options'}; $questionhasinputs = true; $DB->update_record('qtype_stack_inputs', $input); } if ($inputs) { list($test, $params) = $DB->get_in_or_equal(array_keys($inputs)); $params[] = $fromform->id; $DB->delete_records_select('qtype_stack_inputs', 'name ' . $test . ' AND questionid = ?', $params); } if (!$questionhasinputs) { // A question with no inputs is an information item. $DB->set_field('question', 'length', 0, array('id' => $fromform->id)); } $prtnames = stack_utils::extract_placeholders($fromform->questiontext . $options->specificfeedback, 'feedback'); $prts = $DB->get_records('qtype_stack_prts', array('questionid' => $fromform->id), '', 'name, id, questionid'); foreach ($prtnames as $prtname) { if (array_key_exists($prtname, $prts)) { $prt = $prts[$prtname]; unset($prts[$prtname]); } else { $prt = new stdClass(); $prt->questionid = $fromform->id; $prt->name = $prtname; $prt->feedbackvariables = ''; $prt->firstnodename = 0; $prt->id = $DB->insert_record('qtype_stack_prts', $prt); } // Find the root node of the PRT. // Otherwise, if an existing question is being edited, and this is an // existing PRT, base things on the existing question definition. $graph = new stack_abstract_graph(); foreach ($fromform->{$prtname . 'answertest'} as $nodename => $notused) { $truenextnode = $fromform->{$prtname . 'truenextnode'}[$nodename]; $falsenextnode = $fromform->{$prtname . 'falsenextnode'}[$nodename]; if ($truenextnode == -1) { $left = null; } else { $left = $truenextnode + 1; } if ($falsenextnode == -1) { $right = null; } else { $right = $falsenextnode + 1; } $graph->add_node($nodename + 1, $left, $right); } $graph->layout(); $roots = $graph->get_roots(); if (count($roots) != 1 || $graph->get_broken_cycles()) { throw new coding_exception('The PRT ' . $prtname . ' is malformed.'); } reset($roots); $firstnode = key($roots) - 1; $prt->value = $fromform->{$prtname . 'value'}; $prt->autosimplify = $fromform->{$prtname . 'autosimplify'}; $prt->feedbackvariables = $fromform->{$prtname . 'feedbackvariables'}; $prt->firstnodename = $firstnode; $DB->update_record('qtype_stack_prts', $prt); $nodes = $DB->get_records('qtype_stack_prt_nodes', array('questionid' => $fromform->id, 'prtname' => $prtname), '', 'nodename, id, questionid, prtname'); foreach ($fromform->{$prtname . 'answertest'} as $nodename => $notused) { if (array_key_exists($nodename, $nodes)) { $node = $nodes[$nodename]; unset($nodes[$nodename]); } else { $node = new stdClass(); $node->questionid = $fromform->id; $node->prtname = $prtname; $node->nodename = $nodename; $node->truefeedback = ''; $node->falsefeedback = ''; $node->id = $DB->insert_record('qtype_stack_prt_nodes', $node); } $node->answertest = $fromform->{$prtname . 'answertest'}[$nodename]; $node->sans = $fromform->{$prtname . 'sans'}[$nodename]; $node->tans = $fromform->{$prtname . 'tans'}[$nodename]; $node->testoptions = $fromform->{$prtname . 'testoptions'}[$nodename]; $node->quiet = $fromform->{$prtname . 'quiet'}[$nodename]; $node->truescoremode = $fromform->{$prtname . 'truescoremode'}[$nodename]; $node->truescore = $fromform->{$prtname . 'truescore'}[$nodename]; $node->truepenalty = $fromform->{$prtname . 'truepenalty'}[$nodename]; $node->truenextnode = $fromform->{$prtname . 'truenextnode'}[$nodename]; $node->trueanswernote = $fromform->{$prtname . 'trueanswernote'}[$nodename]; $node->truefeedback = $this->import_or_save_files($fromform->{$prtname . 'truefeedback'}[$nodename], $context, 'qtype_stack', 'prtnodetruefeedback', $node->id); $node->truefeedbackformat = $fromform->{$prtname . 'truefeedback'}[$nodename]['format']; $node->falsescoremode = $fromform->{$prtname . 'falsescoremode'}[$nodename]; $node->falsescore = $fromform->{$prtname . 'falsescore'}[$nodename]; $node->falsepenalty = $fromform->{$prtname . 'falsepenalty'}[$nodename]; $node->falsenextnode = $fromform->{$prtname . 'falsenextnode'}[$nodename]; $node->falseanswernote = $fromform->{$prtname . 'falseanswernote'}[$nodename]; $node->falsefeedback = $this->import_or_save_files($fromform->{$prtname . 'falsefeedback'}[$nodename], $context, 'qtype_stack', 'prtnodefalsefeedback', $node->id); $node->falsefeedbackformat = $fromform->{$prtname . 'falsefeedback'}[$nodename]['format']; if ('' === $node->truepenalty) { $node->truepenalty = null; } if ('' === $node->falsepenalty) { $node->falsepenalty = null; } $DB->update_record('qtype_stack_prt_nodes', $node); } if ($nodes) { list($test, $params) = $DB->get_in_or_equal(array_keys($nodes)); $params[] = $fromform->id; $params[] = $prt->name; $DB->delete_records_select('qtype_stack_prt_nodes', 'nodename ' . $test . ' AND questionid = ? AND prtname = ?', $params); } } if ($prts) { list($test, $params) = $DB->get_in_or_equal(array_keys($prts)); $params[] = $fromform->id; $DB->delete_records_select('qtype_stack_prt_nodes', 'prtname ' . $test . ' AND questionid = ?', $params); $DB->delete_records_select('qtype_stack_prts', 'name ' . $test . ' AND questionid = ?', $params); } $this->save_hints($fromform); if (isset($fromform->deployedseeds)) { $DB->delete_records('qtype_stack_deployed_seeds', array('questionid' => $fromform->id)); foreach ($fromform->deployedseeds as $deployedseed) { $record = new stdClass(); $record->questionid = $fromform->id; $record->seed = $deployedseed; $DB->insert_record('qtype_stack_deployed_seeds', $record, false); } } // This is a bit of a hack. If doing 'Make a copy' when saving the // editing form, then detect that here, and try to copy the question // tests from the original question. if (!isset($fromform->testcases) && !empty($fromform->makecopy)) { $oldquestionid = optional_param('id', 0, PARAM_INT); if ($oldquestionid) { $fromform->testcases = $this->load_question_tests($oldquestionid); } } if (isset($fromform->testcases)) { // If the data includes the defintion of the question tests that there // should be (i.e. when doing import) then replace the existing set // of tests with the new one. $this->save_question_tests($fromform->id, $fromform->testcases); } // Irrespective of what else has happened, ensure there is no garbage // in the database, for example if we delete a PRT, remove the expected // values for that PRT while leaving the rest of the testcases alone. list($nametest, $params) = $DB->get_in_or_equal($inputnames, SQL_PARAMS_NAMED, 'input', false, null); $params['questionid'] = $fromform->id; $DB->delete_records_select('qtype_stack_qtest_inputs', 'questionid = :questionid AND inputname ' . $nametest, $params); list($nametest, $params) = $DB->get_in_or_equal($prtnames, SQL_PARAMS_NAMED, 'prt', false, null); $params['questionid'] = $fromform->id; $DB->delete_records_select('qtype_stack_qtest_expected', 'questionid = :questionid AND prtname ' . $nametest, $params); }
public function save_question_options($question) { global $DB, $USER; assert(isset($question->coderunnertype)); $fields = $this->extra_question_fields(); array_shift($fields); // Discard table name $customised = isset($question->customise) && $question->customise; $isprototype = $question->prototypetype != 0; if ($customised && $question->prototypetype == 2 && $question->coderunnertype != $question->typename) { // Saving a new user-defined prototype. // Copy new type name into coderunnertype $question->coderunnertype = $question->typename; } // If we're saving a new prototype, make sure its coderunnertype is // unique by appending a suitable suffix. [Shouldn't happen via // question edit form, but could be a spurious import or a question // duplication mouse click.] if ($question->isnew && $isprototype) { $suffix = ''; $type = $question->coderunnertype; while (true) { try { $row = $this->get_prototype($type . $suffix, $question->context); $suffix = $suffix == '' ? '-1' : $suffix - 1; } catch (coderunner_exception $e) { break; } } $question->coderunnertype = $type . $suffix; } // Set all inherited fields to null if the corresponding form // field is blank or if it's being saved with customise explicitly // turned off and it's not a prototype. $questioninherits = isset($question->customise) && !$question->customise && !$isprototype; foreach ($fields as $field) { $isinherited = !in_array($field, $this->noninherited_fields()); $isblankstring = !isset($question->{$field}) || is_string($question->{$field}) && trim($question->{$field}) === ''; if ($isinherited && ($isblankstring || $questioninherits)) { $question->{$field} = null; } } if (trim($question->sandbox) === 'DEFAULT') { $question->sandbox = null; } parent::save_question_options($question); $testcasetable = "question_coderunner_tests"; if (!isset($question->testcases)) { $this->copy_testcases_from_form($question); } if (!($oldtestcases = $DB->get_records($testcasetable, array('questionid' => $question->id), 'id ASC'))) { $oldtestcases = array(); } foreach ($question->testcases as $tc) { if ($oldtestcase = array_shift($oldtestcases)) { // Existing testcase, so reuse it $tc->id = $oldtestcase->id; $DB->update_record($testcasetable, $tc); } else { // A new testcase $tc->questionid = $question->id; $id = $DB->insert_record($testcasetable, $tc); } } // delete old testcase records foreach ($oldtestcases as $otc) { $DB->delete_records($testcasetable, array('id' => $otc->id)); } // If this is a prototype, clear the caching of any child questions if ($question->prototypetype != 0) { $typename = $question->coderunnertype; $children = $DB->get_records('question_coderunner_options', array('prototypetype' => 0, 'coderunnertype' => $typename)); foreach ($children as $child) { question_bank::notify_question_edited($child->questionid); } } // Lastly, save any datafiles if ($USER->id && isset($question->datafiles)) { // The id check is a hack to deal with phpunit initialisation, when no user exists file_save_draft_area_files($question->datafiles, $question->context->id, 'qtype_coderunner', 'datafile', (int) $question->id, $this->fileoptions); } return true; }
function save_question_options($question) { global $DB, $SESSION; $result = new stdClass(); $context = $question->context; $oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC'); $answers = array(); //$maxfraction = -1; // Insert all the new answers 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; } // 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 = trim($answerdata); // set grade for Answer 1 to 1 (100%) if ($key === 0) { $question->fraction[$key] = 1; } $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]; }*/ } $question->answers = implode(',', $answers); $parentresult = parent::save_question_options($question); if ($parentresult !== null) { // Parent function returns null if all is OK return $parentresult; } // 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)); } $this->save_hints($question); // JR dec 2011 unset alternateanswers and alternatecorrectanswers after question has been edited, just in case $qid = $question->id; if (isset($SESSION->qtype_regexp_question->alternateanswers[$qid])) { unset($SESSION->qtype_regexp_question->alternateanswers[$qid]); } if (isset($SESSION->qtype_regexp_question->alternatecorrectanswers[$qid])) { unset($SESSION->qtype_regexp_question->alternatecorrectanswers[$qid]); } // Perform sanity checks on fractional grades /* if ($maxfraction != 1) { $result->noticeyesno = get_string('fractionsnomax', 'quiz', $maxfraction * 100); return $result; }*/ }