/** * Saves (creates or updates) a question. * * Given some question info and some data about the answers * this function parses, organises and saves the question * It is used by {@link question.php} when saving new data from * a form, and also by {@link import.php} when importing questions * This function in turn calls {@link save_question_options} * to save question-type specific data. * * Whether we are saving a new question or updating an existing one can be * determined by testing !empty($question->id). If it is not empty, we are updating. * * The question will be saved in category $form->category. * * @param object $question the question object which should be updated. For a new question will be mostly empty. * @param object $form the object containing the information to save, as if from the question editing form. * @param object $course not really used any more. * @return object On success, return the new question object. On failure, * return an object as follows. If the error object has an errors field, * display that as an error message. Otherwise, the editing form will be * redisplayed with validation errors, from validation_errors field, which * is itself an object, shown next to the form fields. (I don't think this is accurate any more.) */ function save_question($question, $form, $course) { global $USER; // This default implementation is suitable for most // question types. // First, save the basic question itself $question->name = trim($form->name); $question->questiontext = trim($form->questiontext); $question->questiontextformat = $form->questiontextformat; $question->parent = isset($form->parent) ? $form->parent : 0; $question->length = $this->actual_number_of_questions($question); $question->penalty = isset($form->penalty) ? $form->penalty : 0; if (empty($form->image)) { $question->image = ''; } else { $question->image = $form->image; } if (empty($form->generalfeedback)) { $question->generalfeedback = ''; } else { $question->generalfeedback = trim($form->generalfeedback); } if (empty($question->name)) { $question->name = shorten_text(strip_tags($question->questiontext), 15); if (empty($question->name)) { $question->name = '-'; } } if ($question->penalty > 1 or $question->penalty < 0) { $question->errors['penalty'] = get_string('invalidpenalty', 'quiz'); } if (isset($form->defaultgrade)) { $question->defaultgrade = $form->defaultgrade; } list($question->category) = explode(',', $form->category); if (!empty($question->id)) { /// Question already exists, update. $question->modifiedby = $USER->id; $question->timemodified = time(); if (!update_record('question', $question)) { error('Could not update question!'); } } else { /// New question. // Set the unique code $question->stamp = make_unique_id_code(); $question->createdby = $USER->id; $question->modifiedby = $USER->id; $question->timecreated = time(); $question->timemodified = time(); if (!($question->id = insert_record('question', $question))) { error('Could not insert new question!'); } } // Now to save all the answers and type-specific options $form->id = $question->id; $form->qtype = $question->qtype; $form->category = $question->category; $form->questiontext = $question->questiontext; $result = $this->save_question_options($form); if (!empty($result->error)) { error($result->error); } if (!empty($result->notice)) { notice($result->notice, "question.php?id={$question->id}"); } if (!empty($result->noticeyesno)) { notice_yesno($result->noticeyesno, "question.php?id={$question->id}&courseid={$course->id}", "edit.php?courseid={$course->id}"); print_footer($course); exit; } // Give the question a unique version stamp determined by question_hash() if (!set_field('question', 'version', question_hash($question), 'id', $question->id)) { error('Could not update question version field'); } return $question; }
/** * Process the file * This method should not normally be overidden * @param object $category * @return bool success */ public function importprocess($category) { global $USER, $CFG, $DB, $OUTPUT; $context = $category->context; $this->importcontext = $context; // reset the timer in case file upload was slow set_time_limit(0); // STAGE 1: Parse the file echo $OUTPUT->notification(get_string('parsingquestions', 'question'), 'notifysuccess'); if (! $lines = $this->readdata($this->filename)) { echo $OUTPUT->notification(get_string('cannotread', 'question')); return false; } if (!$questions = $this->readquestions($lines, $context)) { // Extract all the questions echo $OUTPUT->notification(get_string('noquestionsinfile', 'question')); return false; } // STAGE 2: Write data to database echo $OUTPUT->notification(get_string('importingquestions', 'question', $this->count_questions($questions)), 'notifysuccess'); // check for errors before we continue if ($this->stoponerror and ($this->importerrors>0)) { echo $OUTPUT->notification(get_string('importparseerror', 'question')); return true; } // get list of valid answer grades $gradeoptionsfull = question_bank::fraction_options_full(); // check answer grades are valid // (now need to do this here because of 'stop on error': MDL-10689) $gradeerrors = 0; $goodquestions = array(); foreach ($questions as $question) { if (!empty($question->fraction) and (is_array($question->fraction))) { $fractions = $question->fraction; $answersvalid = true; // in case they are! foreach ($fractions as $key => $fraction) { $newfraction = match_grade_options($gradeoptionsfull, $fraction, $this->matchgrades); if ($newfraction === false) { $answersvalid = false; } else { $fractions[$key] = $newfraction; } } if (!$answersvalid) { echo $OUTPUT->notification(get_string('invalidgrade', 'question')); ++$gradeerrors; continue; } else { $question->fraction = $fractions; } } $goodquestions[] = $question; } $questions = $goodquestions; // check for errors before we continue if ($this->stoponerror && $gradeerrors > 0) { return false; } // count number of questions processed $count = 0; foreach ($questions as $question) { // Process and store each question // reset the php timeout set_time_limit(0); // check for category modifiers if ($question->qtype == 'category') { if ($this->catfromfile) { // find/create category object $catpath = $question->category; $newcategory = $this->create_category_path($catpath); if (!empty($newcategory)) { $this->category = $newcategory; } } continue; } $question->context = $context; $count++; echo "<hr /><p><b>$count</b>. ".$this->format_question_text($question)."</p>"; $question->category = $this->category->id; $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed) $question->createdby = $USER->id; $question->timecreated = time(); $question->modifiedby = $USER->id; $question->timemodified = time(); $question->id = $DB->insert_record('question', $question); if (isset($question->questiontextfiles)) { foreach ($question->questiontextfiles as $file) { question_bank::get_qtype($question->qtype)->import_file( $context, 'question', 'questiontext', $question->id, $file); } } if (isset($question->generalfeedbackfiles)) { foreach ($question->generalfeedbackfiles as $file) { question_bank::get_qtype($question->qtype)->import_file( $context, 'question', 'generalfeedback', $question->id, $file); } } $this->questionids[] = $question->id; // Now to save all the answers and type-specific options $result = question_bank::get_qtype($question->qtype)->save_question_options($question); if (!empty($CFG->usetags) && isset($question->tags)) { require_once($CFG->dirroot . '/tag/lib.php'); tag_set('question', $question->id, $question->tags); } if (!empty($result->error)) { echo $OUTPUT->notification($result->error); return false; } if (!empty($result->notice)) { echo $OUTPUT->notification($result->notice); return true; } // Give the question a unique version stamp determined by question_hash() $DB->set_field('question', 'version', question_hash($question), array('id' => $question->id)); } return true; }
function importprocess($filename) { global $CFG, $USER, $strimportquestions, $form, $question_category, $category, $COURSE, $hostname, $mdapath, $mdbpath; if (PHP_OS == "Linux" and isset($hostname)) { $hostname = trim($hostname); // test the ODBC socket server connection // if failure, unset hostname and set hostname_access_error $question_categories = $this->getquestioncategories($mdbpath, $mdapath, $hostname); if (!$question_categories) { $hostname_access_error = $hostname . " "; unset($hostname); } else { $hostname_access_error = 0; } } if (PHP_OS == "Linux" and !isset($hostname)) { // copy the file to a semi-permanent location if (!($basedir = make_upload_directory("{$COURSE->id}"))) { error("The site administrator needs to fix the file permissions for the data directory"); } if (!isset($hostname_access_error)) { $bname = basename($filename); $cleanfilename = clean_filename($bname); if ($cleanfilename) { $newfile = "{$basedir}/{$cleanfilename}"; if (move_uploaded_file($filename, $newfile)) { chmod($newfile, 0666); clam_log_upload($newfile, $COURSE); } else { notify(get_string("uploadproblem", "", $filename)); } } $filename = $newfile; } print_heading_with_help($strimportquestions, "import", "quiz"); print_simple_box_start("center"); if ($hostname_access_error) { notify("couldn't connect to ODBC Socket Server on " . $hostname_access_error); } echo "<form method=\"post\" action=\"import.php\">"; echo '<fieldset class="invisiblefieldset">'; echo "<table cellpadding=\"5\">"; echo "<tr><td align=\"right\">"; echo "What is the hostname or IP address of the ODBC Socket Server:</td><td>"; echo " <input name=\"hostname\" type=\"text\" size=\"50\" value=\"" . stripslashes($hostname_access_error) . "\" />"; echo " <input name=\"filename\" type=\"hidden\" value=\"" . $filename . "\" />"; echo " <input name=\"category\" type=\"hidden\" value=\"" . $category->id . "\" />"; echo " <input name=\"format\" type=\"hidden\" value=\"" . $form->format . "\" />"; echo "</td><td> </td></tr>"; echo "<tr><td align=\"right\">"; echo "What is the location of the database (.mdb file) on the Socket Server:</td><td>"; echo " <input name=\"mdbpath\" type=\"text\" size=\"50\" value=\"" . stripslashes($mdbpath) . "\" />"; echo "</td><td> </td></tr>"; echo "<tr><td align=\"right\">"; echo "What is the location of the system database (System.mda file) on the Socket Server:</td><td>"; echo " <input name=\"mdapath\" type=\"text\" size=\"50\" value=\"" . stripslashes($mdapath) . "\" />"; echo "</td><td> </td></tr>"; echo "<tr><td> </td><td>"; echo " <input type=\"submit\" name=\"save\" value=\"Connect to Server\" />"; echo "</td></tr>"; echo "</table>"; echo '</fieldset>'; echo "</form>"; print_simple_box_end(); print_footer($COURSE); exit; } // we get here if running windows or after connect to ODBC socket server on linux // // this generates the page to choose categories of questions to import // if (!isset($question_category)) { if (PHP_OS == "WINNT") { // copy the file to a semi-permanent location if (!($basedir = make_upload_directory("{$COURSE->id}"))) { error("The site administrator needs to fix the file permissions for the data directory"); } $bname = basename($filename); $cleanfilename = clean_filename($bname); if ($cleanfilename) { $newfile = "{$basedir}/{$cleanfilename}"; if (move_uploaded_file($filename, $newfile)) { chmod($newfile, 0666); clam_log_upload($newfile, $COURSE); } else { notify(get_string("uploadproblem", "", $filename)); } } $filename = $newfile; } // end of file copy // don't have to do this on linux, since it's alreay been done in the test above if (PHP_OS == "WINNT") { $question_categories = $this->getquestioncategories($filename); } // print the intermediary form if (!($categories = question_category_options($COURSE->id, true))) { error("No categories!"); } print_heading_with_help($strimportquestions, "import", "quiz"); print_simple_box_start("center"); echo "<form method=\"post\" action=\"import.php\">"; echo '<fieldset class="invisiblefieldset">'; echo "<table cellpadding=\"5\">"; echo "<tr><td align=\"right\">"; echo "Choose a category of questions to import:</td><td>"; asort($question_categories); choose_from_menu($question_categories, "question_category", "All Categories", "All Categories", "", "allcategories"); echo " <input name=\"filename\" type=\"hidden\" value=\"" . $filename . "\" />"; echo " <input name=\"category\" type=\"hidden\" value=\"" . $category->id . "\" />"; echo " <input name=\"format\" type=\"hidden\" value=\"" . $form->format . "\" />"; if (PHP_OS == "Linux") { echo " <input name=\"hostname\" type=\"hidden\" value=\"" . stripslashes(trim($hostname)) . "\" />"; echo " <input name=\"mdbpath\" type=\"hidden\" value=\"" . stripslashes($mdbpath) . "\" />"; echo " <input name=\"mdapath\" type=\"hidden\" value=\"" . stripslashes($mdapath) . "\" />"; } echo "</td><td> </td>"; echo "</tr><tr><td> </td><td>"; echo " <input type=\"submit\" name=\"save\" value=\"Import Questions\" />"; echo "</td></tr>"; echo "</table>"; echo '</fieldset>'; echo "</form>"; print_simple_box_end(); print_footer($COURSE); exit; } // // this is the main import section // notify("Importing questions"); if (PHP_OS == "Linux") { $hostname = trim($hostname); $records = $this->getquestions($mdbpath, $question_category, $mdapath, $hostname); } else { $records = $this->getquestions($filename, $question_category); } foreach ($records as $qrec) { $question = $this->defaultquestion(); if ($qrec[9] != "") { $question->image = $qrec[9]; } // 0 Selected // 1 PracticeTestOK? // 2 QuestionText // 3 QuestionType // 4 Option1Text // 5 Option2Text // 6 Option3Text // 7 Option4Text // 8 CorrectAnswer // 9 Graphic // 10 Module // 11 ChapterNumber // 12 PageNumber $ref = "Answer can be found in chapter " . $qrec[11] . ", page " . $qrec[12] . "."; switch ($qrec[3]) { case 1: $question->qtype = MULTICHOICE; // MULTICHOICE, SHORTANSWER, TRUEFALSE // echo "<pre>";echo htmlspecialchars($qrec[2]); echo "</pre>"; $question->questiontext = addslashes(trim($qrec[2])); // echo "<pre>";echo $question->questiontext; echo "</pre>"; $question->name = preg_replace("/<br />/", "", $question->questiontext); $question->single = 1; // Only one answer is allowed -- used for multiple choicers $fractionset = 0; for ($i = 4; $i <= 7; $i++) { if ($qrec[$i] != "") { $question->answer[$i - 3] = addslashes($qrec[$i]); if ($qrec[8] == $i - 3) { // if this is the index of CorrectAnswer $question->fraction[$i - 3] = 1; $fractionset = 1; } else { $question->fraction[$i - 3] = 0; } $question->feedback[$i - 3] = ($qrec[8] == $i - 3 ? "Correct. " : "Incorrect. ") . $ref; } } if ($fractionset == 0) { $question->fraction[1] = 1; } break; case 2: // TRUE FALSE $question->qtype = TRUEFALSE; $question->questiontext = addslashes(trim($qrec[2])); $question->name = preg_replace("/<br />/", "", $question->questiontext); // for TF, $question->answer should be 1 for true, 0 for false if ($qrec[8] == "T") { $question->answer = 1; } else { $question->answer = 0; } // for TF, use $question->feedbacktrue and feedbackfalse $question->feedbacktrue = ($qrec[8] == "T" ? "Correct. " : "Incorrect. ") . $ref; $question->feedbackfalse = ($qrec[8] == "F" ? "Correct. " : "Incorrect. ") . $ref; break; case 3: $question->qtype = SHORTANSWER; $question->questiontext = addslashes(trim($qrec[2])); // echo "<pre>";echo $question->questiontext; echo "</pre>"; $question->name = preg_replace("/<br />/", "", $question->questiontext); $question->usecase = 0; // Ignore case -- for SHORT ANSWER questions $answers = explode("~", $qrec[8]); $question->answer[0] = " "; $question->fraction[0] = 1; for ($i = 0; $i < count($answers); $i++) { $question->answer[$i] = addslashes(trim($answers[$i])); $question->feedback[$i] = $ref; $question->fraction[$i] = 1; // 1 for 100%, 0 for none or somewhere in between } break; case 4: $question = 0; notify("Cannot use essay questions - skipping question " . $qrec[2] . " " . $ref); break; default: $question = 0; notify("Misformatted Record. Question Skipped."); break; } if ($question) { $questions[] = $question; } } $count = 0; // process all the questions if (PHP_OS == "WINNT") { $filename = str_replace("\\\\", "\\", $filename); $filename = str_replace("/", "\\", $filename); } foreach ($questions as $question) { // Process and store each question $count++; echo "<hr /><p><b>{$count}</b>. " . stripslashes($question->questiontext) . "</p>"; $question->category = $this->category->id; $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed) $question->createdby = $USER->id; $question->timecreated = time(); if (!($question->id = insert_record("question", $question))) { error("Could not insert new question!"); } $this->questionids[] = $question->id; // Now to save all the answers and type-specific options $result = save_question_options($question); if (!empty($result->error)) { notify($result->error); $this->deletedatabase($filename); return false; } if (!empty($result->notice)) { notify($result->notice); $this->deletedatabase($filename); return true; } // Give the question a unique version stamp determined by question_hash() set_field('question', 'version', question_hash($question), 'id', $question->id); } $this->deletedatabase($filename); return true; }
/** * Saves (creates or updates) a question. * * Given some question info and some data about the answers * this function parses, organises and saves the question * It is used by {@link question.php} when saving new data from * a form, and also by {@link import.php} when importing questions * This function in turn calls {@link save_question_options} * to save question-type specific data. * * Whether we are saving a new question or updating an existing one can be * determined by testing !empty($question->id). If it is not empty, we are updating. * * The question will be saved in category $form->category. * * @param object $question the question object which should be updated. For a * new question will be mostly empty. * @param object $form the object containing the information to save, as if * from the question editing form. * @param object $course not really used any more. * @return object On success, return the new question object. On failure, * return an object as follows. If the error object has an errors field, * display that as an error message. Otherwise, the editing form will be * redisplayed with validation errors, from validation_errors field, which * is itself an object, shown next to the form fields. (I don't think this * is accurate any more.) */ public function save_question($question, $form) { global $USER, $DB, $OUTPUT; list($question->category) = explode(',', $form->category); $context = $this->get_context_by_category_id($question->category); // This default implementation is suitable for most // question types. // First, save the basic question itself. $question->name = trim($form->name); $question->parent = isset($form->parent) ? $form->parent : 0; $question->length = $this->actual_number_of_questions($question); $question->penalty = isset($form->penalty) ? $form->penalty : 0; if (empty($form->questiontext['text'])) { $question->questiontext = ''; } else { $question->questiontext = trim($form->questiontext['text']); } $question->questiontextformat = !empty($form->questiontext['format']) ? $form->questiontext['format'] : 0; if (empty($form->generalfeedback['text'])) { $question->generalfeedback = ''; } else { $question->generalfeedback = trim($form->generalfeedback['text']); } $question->generalfeedbackformat = !empty($form->generalfeedback['format']) ? $form->generalfeedback['format'] : 0; if (empty($question->name)) { $question->name = shorten_text(strip_tags($form->questiontext['text']), 15); if (empty($question->name)) { $question->name = '-'; } } if ($question->penalty > 1 or $question->penalty < 0) { $question->errors['penalty'] = get_string('invalidpenalty', 'question'); } if (isset($form->defaultmark)) { $question->defaultmark = $form->defaultmark; } // If the question is new, create it. if (empty($question->id)) { // Set the unique code. $question->stamp = make_unique_id_code(); $question->createdby = $USER->id; $question->timecreated = time(); $question->id = $DB->insert_record('question', $question); } // Now, whether we are updating a existing question, or creating a new // one, we have to do the files processing and update the record. // Question already exists, update. $question->modifiedby = $USER->id; $question->timemodified = time(); if (!empty($question->questiontext) && !empty($form->questiontext['itemid'])) { $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) && !empty($form->generalfeedback['itemid'])) { $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); // Now to save all the answers and type-specific options. $form->id = $question->id; $form->qtype = $question->qtype; $form->category = $question->category; $form->questiontext = $question->questiontext; $form->questiontextformat = $question->questiontextformat; // Current context. $form->context = $context; $result = $this->save_question_options($form); if (!empty($result->error)) { print_error($result->error); } if (!empty($result->notice)) { notice($result->notice, "question.php?id=$question->id"); } if (!empty($result->noticeyesno)) { throw new coding_exception( '$result->noticeyesno no longer supported in save_question.'); } // Give the question a unique version stamp determined by question_hash(). $DB->set_field('question', 'version', question_hash($question), array('id' => $question->id)); return $question; }
/** * Process the file * This method should not normally be overidden * @return boolean success */ function importprocess() { global $USER; // reset the timer in case file upload was slow @set_time_limit(); // STAGE 1: Parse the file notify(get_string('parsingquestions', 'quiz')); if (!($lines = $this->readdata($this->filename))) { notify(get_string('cannotread', 'quiz')); return false; } if (!($questions = $this->readquestions($lines))) { // Extract all the questions notify(get_string('noquestionsinfile', 'quiz')); return false; } // STAGE 2: Write data to database notify(get_string('importingquestions', 'quiz', $this->count_questions($questions))); // check for errors before we continue if ($this->stoponerror and $this->importerrors > 0) { notify(get_string('importparseerror', 'quiz')); return true; } // get list of valid answer grades $grades = get_grade_options(); $gradeoptionsfull = $grades->gradeoptionsfull; // check answer grades are valid // (now need to do this here because of 'stop on error': MDL-10689) $gradeerrors = 0; $goodquestions = array(); foreach ($questions as $question) { if (!empty($question->fraction) and is_array($question->fraction)) { $fractions = $question->fraction; $answersvalid = true; // in case they are! foreach ($fractions as $key => $fraction) { $newfraction = match_grade_options($gradeoptionsfull, $fraction, $this->matchgrades); if ($newfraction === false) { $answersvalid = false; } else { $fractions[$key] = $newfraction; } } if (!$answersvalid) { notify(get_string('matcherror', 'quiz')); ++$gradeerrors; continue; } else { $question->fraction = $fractions; } } $goodquestions[] = $question; } $questions = $goodquestions; // check for errors before we continue if ($this->stoponerror and $gradeerrors > 0) { return false; } // count number of questions processed $count = 0; foreach ($questions as $question) { // Process and store each question // reset the php timeout @set_time_limit(); // check for category modifiers if ($question->qtype == 'category') { if ($this->catfromfile) { // find/create category object $catpath = $question->category; $newcategory = $this->create_category_path($catpath, '/'); if (!empty($newcategory)) { $this->category = $newcategory; } } continue; } $count++; echo "<hr /><p><b>{$count}</b>. " . $this->format_question_text($question) . "</p>"; $question->category = $this->category->id; $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed) $question->createdby = $USER->id; $question->timecreated = time(); if (!($question->id = insert_record("question", $question))) { error(get_string('cannotinsert', 'quiz')); } $this->questionids[] = $question->id; // Now to save all the answers and type-specific options global $QTYPES; $result = $QTYPES[$question->qtype]->save_question_options($question); if (!empty($result->error)) { notify($result->error); return false; } if (!empty($result->notice)) { notify($result->notice); return true; } // Give the question a unique version stamp determined by question_hash() set_field('question', 'version', question_hash($question), 'id', $question->id); } return true; }
/** * Process the file * This method should not normally be overidden * @param object $category * @return bool success */ public function importprocess($category) { global $USER, $CFG, $DB, $OUTPUT; // Raise time and memory, as importing can be quite intensive. core_php_time_limit::raise(); raise_memory_limit(MEMORY_EXTRA); // STAGE 1: Parse the file echo $OUTPUT->notification(get_string('parsingquestions', 'question'), 'notifysuccess'); if (!($lines = $this->readdata($this->filename))) { echo $OUTPUT->notification(get_string('cannotread', 'question')); return false; } if (!($questions = $this->readquestions($lines))) { // Extract all the questions echo $OUTPUT->notification(get_string('noquestionsinfile', 'question')); return false; } // STAGE 2: Write data to database echo $OUTPUT->notification(get_string('importingquestions', 'question', $this->count_questions($questions)), 'notifysuccess'); // check for errors before we continue if ($this->stoponerror and $this->importerrors > 0) { echo $OUTPUT->notification(get_string('importparseerror', 'question')); return true; } // get list of valid answer grades $gradeoptionsfull = question_bank::fraction_options_full(); // check answer grades are valid // (now need to do this here because of 'stop on error': MDL-10689) $gradeerrors = 0; $goodquestions = array(); foreach ($questions as $question) { if (!empty($question->fraction) and is_array($question->fraction)) { $fractions = $question->fraction; $invalidfractions = array(); foreach ($fractions as $key => $fraction) { $newfraction = match_grade_options($gradeoptionsfull, $fraction, $this->matchgrades); if ($newfraction === false) { $invalidfractions[] = $fraction; } else { $fractions[$key] = $newfraction; } } if ($invalidfractions) { echo $OUTPUT->notification(get_string('invalidgrade', 'question', implode(', ', $invalidfractions))); ++$gradeerrors; continue; } else { $question->fraction = $fractions; } } $goodquestions[] = $question; } $questions = $goodquestions; // check for errors before we continue if ($this->stoponerror && $gradeerrors > 0) { return false; } // count number of questions processed $count = 0; foreach ($questions as $question) { // Process and store each question $transaction = $DB->start_delegated_transaction(); // reset the php timeout core_php_time_limit::raise(); // check for category modifiers if ($question->qtype == 'category') { if ($this->catfromfile) { // find/create category object $catpath = $question->category; $newcategory = $this->create_category_path($catpath); if (!empty($newcategory)) { $this->category = $newcategory; } } $transaction->allow_commit(); continue; } $question->context = $this->importcontext; $count++; echo "<hr /><p><b>{$count}</b>. " . $this->format_question_text($question) . "</p>"; $question->category = $this->category->id; $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed) $question->createdby = $USER->id; $question->timecreated = time(); $question->modifiedby = $USER->id; $question->timemodified = time(); $fileoptions = array('subdirs' => true, 'maxfiles' => -1, 'maxbytes' => 0); $question->id = $DB->insert_record('question', $question); if (isset($question->questiontextitemid)) { $question->questiontext = file_save_draft_area_files($question->questiontextitemid, $this->importcontext->id, 'question', 'questiontext', $question->id, $fileoptions, $question->questiontext); } else { if (isset($question->questiontextfiles)) { foreach ($question->questiontextfiles as $file) { question_bank::get_qtype($question->qtype)->import_file($this->importcontext, 'question', 'questiontext', $question->id, $file); } } } if (isset($question->generalfeedbackitemid)) { $question->generalfeedback = file_save_draft_area_files($question->generalfeedbackitemid, $this->importcontext->id, 'question', 'generalfeedback', $question->id, $fileoptions, $question->generalfeedback); } else { if (isset($question->generalfeedbackfiles)) { foreach ($question->generalfeedbackfiles as $file) { question_bank::get_qtype($question->qtype)->import_file($this->importcontext, 'question', 'generalfeedback', $question->id, $file); } } } $DB->update_record('question', $question); $this->questionids[] = $question->id; // Now to save all the answers and type-specific options $result = question_bank::get_qtype($question->qtype)->save_question_options($question); if (!empty($CFG->usetags) && isset($question->tags)) { require_once $CFG->dirroot . '/tag/lib.php'; tag_set('question', $question->id, $question->tags, 'core_question', $question->context->id); } if (!empty($result->error)) { echo $OUTPUT->notification($result->error); // Can't use $transaction->rollback(); since it requires an exception, // and I don't want to rewrite this code to change the error handling now. $DB->force_transaction_rollback(); return false; } $transaction->allow_commit(); if (!empty($result->notice)) { echo $OUTPUT->notification($result->notice); return true; } // Give the question a unique version stamp determined by question_hash() $DB->set_field('question', 'version', question_hash($question), array('id' => $question->id)); } return true; }
function RWSAAQRand() { global $CFG; global $DB; global $RWSUID; RWSCMAuth(); RWSCRAuth(); RWSCMUSvc(); RWSCMMaint(); $r_pm = RWSGSOpt("quizid", PARAM_ALPHANUM); if ($r_pm === false || strlen($r_pm) == 0) { RWSSErr("2067"); } $r_qzmi = intval($r_pm); $r_cmod = RWSCMUQuiz($r_qzmi); $r_cid = $r_cmod->course; RWSCMUCourse($r_cid, true); $r_mr = $DB->get_record("modules", array("id" => $r_cmod->module)); if ($r_mr === false) { RWSSErr("2043"); } $r_qiz = $DB->get_record($r_mr->name, array("id" => $r_cmod->instance)); if ($r_qiz === false) { RWSSErr("2044"); } $r_pm = RWSGSOpt("qcatid", PARAM_ALPHANUM); if ($r_pm === false || strlen($r_pm) == 0) { RWSSErr("2064"); } $r_qci = intval($r_pm); $r_qca = $DB->get_record("question_categories", array("id" => $r_qci)); if ($r_qca === false) { RWSSErr("2065"); } if (respondusws_floatcompare($CFG->version, 2013111800, 2) >= 0) { $r_ctx = context::instance_by_id($r_qca->contextid); } else { $r_ctx = get_context_instance_by_id($r_qca->contextid); } $r_qcci = RWSGCFCat($r_ctx); if ($r_qcci != $r_cid) { if (is_siteadmin($RWSUID)) { if ($r_qcci != SITEID) { RWSSErr("2109"); } } else { RWSSErr("2084"); } } $r_pm = RWSGSOpt("qcount", PARAM_ALPHANUM); if ($r_pm === false || strlen($r_pm) == 0) { RWSSErr("2085"); } $r_qct = intval($r_pm); if ($r_qct <= 0) { RWSSErr("2085"); } $r_pm = RWSGSOpt("qgrade", PARAM_NOTAGS); if ($r_pm === false || strlen($r_pm) == 0) { RWSSErr("2086"); } $r_qg = round(floatval($r_pm)); if ($r_qg <= 0) { RWSSErr("2086"); } $r_mr = $DB->get_record("modules", array("id" => $r_cmod->module)); if ($r_mr === false) { RWSSErr("2043"); } $r_qiz = $DB->get_record($r_mr->name, array("id" => $r_cmod->instance)); if ($r_qiz === false) { RWSSErr("2044"); } if (!isset($r_qiz->instance)) { $r_qiz->instance = $r_qiz->id; } $r_aerr = 0; for ($r_i = 0; $r_i < $r_qct; $r_i++) { $r_qst = new stdClass(); $r_qst->qtype = RWSRND; $r_qst->parent = 0; $r_qst->hidden = 0; $r_qst->length = 1; $r_qst->questiontext = 1; if (respondusws_floatcompare($CFG->version, 2011070100, 2) >= 0) { $r_rqt = question_bank::get_qtype("random"); $r_qst->name = $r_rqt->question_name($r_qca, !empty($r_qst->questiontext)); } else { $r_qst->name = random_qtype::question_name($r_qca, !empty($r_qst->questiontext)); } $r_qst->questiontextformat = FORMAT_HTML; $r_qst->penalty = 0; if (respondusws_floatcompare($CFG->version, 2011070100, 2) >= 0) { $r_qst->defaultmark = $r_qg; } else { $r_qst->defaultgrade = $r_qg; } $r_qst->generalfeedback = ""; $r_qst->generalfeedbackformat = FORMAT_HTML; $r_qst->category = $r_qca->id; $r_qst->stamp = make_unique_id_code(); $r_qst->createdby = $RWSUID; $r_qst->modifiedby = $RWSUID; $r_qst->timecreated = time(); $r_qst->timemodified = time(); $r_qst->id = $DB->insert_record("question", $r_qst); $DB->set_field("question", "parent", $r_qst->id, array("id" => $r_qst->id)); $r_h = question_hash($r_qst); $DB->set_field("question", "version", $r_h, array("id" => $r_qst->id)); if (respondusws_floatcompare($CFG->version, 2011070100, 2) >= 0) { quiz_add_quiz_question($r_qst->id, $r_qiz); } else { $r_ok = quiz_add_quiz_question($r_qst->id, $r_qiz); if (!$r_ok) { $DB->delete_records("question", array("id" => $r_qst->id)); $r_aerr++; } } } if ($r_aerr > 0) { RWSSErr("2087,{$r_aerr}"); } if ($r_aerr < $r_qct) { quiz_delete_previews($r_qiz); } if (respondusws_floatcompare($CFG->version, 2014051200, 2) >= 0) { quiz_update_sumgrades($r_qiz); } else { $r_qiz->grades = quiz_get_all_question_grades($r_qiz); $r_sumg = array_sum($r_qiz->grades); $DB->set_field("quiz", "sumgrades", $r_sumg, array("id" => $r_qiz->id)); } RWSSStat("1006"); }
protected function save_question($question, $course, $category) { global $USER, $DB; $this->reset_time_limit(); if (!isset($question->course)) { $question->course = $course->id; } $question->category = $category->id; $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed) $question->createdby = $USER->id; $question->modifiedby = $USER->id; $question->timecreated = time(); $question->timemodified = $question->timecreated; $question->id = $DB->insert_record("question", $question); //save type-specific options global $QTYPES; $result = $QTYPES[$question->qtype]->save_question_options($question); // Give the question a unique version stamp determined by question_hash() $DB->set_field('question', 'version', question_hash($question), array('id' => $question->id)); $this->save_resources($question); return $result; }
/** * Saves or updates a question after editing by a teacher * * Given some question info and some data about the answers * this function parses, organises and saves the question * It is used by {@link question.php} when saving new data from * a form, and also by {@link import.php} when importing questions * This function in turn calls {@link save_question_options} * to save question-type specific options * @param object $question the question object which should be updated * @param object $form the form submitted by the teacher * @param object $course the course we are in * @return object On success, return the new question object. On failure, * return an object as follows. If the error object has an errors field, * display that as an error message. Otherwise, the editing form will be * redisplayed with validation errors, from validation_errors field, which * is itself an object, shown next to the form fields. */ function save_question($question, $form, $course) { global $USER; // This default implementation is suitable for most // question types. // First, save the basic question itself $question->name = trim($form->name); $question->questiontext = trim($form->questiontext); $question->questiontextformat = $form->questiontextformat; $question->parent = isset($form->parent) ? $form->parent : 0; $question->length = $this->actual_number_of_questions($question); $question->penalty = isset($form->penalty) ? $form->penalty : 0; if (empty($form->image)) { $question->image = ""; } else { $question->image = $form->image; } if (empty($form->generalfeedback)) { $question->generalfeedback = ''; } else { $question->generalfeedback = trim($form->generalfeedback); } if (empty($question->name)) { $question->name = shorten_text(strip_tags($question->questiontext), 15); if (empty($question->name)) { $question->name = '-'; } } if ($question->penalty > 1 or $question->penalty < 0) { $question->errors['penalty'] = get_string('invalidpenalty', 'quiz'); } if (isset($form->defaultgrade)) { $question->defaultgrade = $form->defaultgrade; } if (!empty($question->id)) { // Question already exists if (isset($form->categorymoveto)) { question_require_capability_on($question, 'move'); list($question->category, $movetocontextid) = explode(',', $form->categorymoveto); //don't need to test add permission of category we are moving question to. //Only categories that we have permission to add //a question to will get through the form cleaning code for the select box. } // keep existing unique stamp code $question->stamp = get_field('question', 'stamp', 'id', $question->id); $question->modifiedby = $USER->id; $question->timemodified = time(); if (!update_record('question', $question)) { error('Could not update question!'); } } else { // Question is a new one if (isset($form->categorymoveto)) { // Doing save as new question, and we have move rights. list($question->category, $notused) = explode(',', $form->categorymoveto); //don't need to test add permission of category we are moving question to. //Only categories that we have permission to add //a question to will get through the form cleaning code for the select box. } else { // Really a new question. list($question->category, $notused) = explode(',', $form->category); } // Set the unique code $question->stamp = make_unique_id_code(); $question->createdby = $USER->id; $question->modifiedby = $USER->id; $question->timecreated = time(); $question->timemodified = time(); if (!($question->id = insert_record('question', $question))) { print_object($question); error('Could not insert new question!'); } } // Now to save all the answers and type-specific options $form->id = $question->id; $form->qtype = $question->qtype; $form->category = $question->category; $form->questiontext = $question->questiontext; $result = $this->save_question_options($form); if (!empty($result->error)) { error($result->error); } if (!empty($result->notice)) { notice($result->notice, "question.php?id={$question->id}"); } if (!empty($result->noticeyesno)) { notice_yesno($result->noticeyesno, "question.php?id={$question->id}&courseid={$course->id}", "edit.php?courseid={$course->id}"); print_footer($course); exit; } // Give the question a unique version stamp determined by question_hash() if (!set_field('question', 'version', question_hash($question), 'id', $question->id)) { error('Could not update question version field'); } return $question; }