Пример #1
0
 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;
 }
Пример #3
0
 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);
 }
Пример #4
0
 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);
 }
Пример #5
0
 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;
 }
Пример #6
0
 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;
             }*/
 }