category = $category; // Important $this->course = $course; return true; } /** * * @PARAM $matchgrades string 'error' or 'nearest', mismatched grades handling */ function importprocess($filename, $matchgrades='error') { /// Processes a given file. There's probably little need to change this if (! $lines = $this->readdata($filename)) { notify( get_string('cannotread','quiz') ); return false; } if (! $questions = $this->readquestions($lines)) { // Extract all the questions notify( get_string('noquestionsinfile','quiz') ); return false; } notify( get_string('importingquestions','quiz',count($questions)) ); // get list of valid answer grades $grades = get_grade_options(); $gradeoptionsfull = $grades->gradeoptionsfull; $count = 0; foreach ($questions as $question) { // Process and store each question $count++; echo "

$count. ".stripslashes($question->questiontext)."

"; // check for answer grades validity (must match fixed list of grades) $fractions = $question->fraction; if (!empty($fractions)) { $answersvalid = true; // in case they are! foreach ($fractions as $key => $fraction) { $newfraction = match_grade_options($gradeoptionsfull, $fraction, $matchgrades); if ($newfraction===false) { $answersvalid = false; } else { $fractions[$key] = $newfraction; } } if (!$answersvalid) { notify( get_string('matcherror','quiz') ); continue; } else { $question->fraction = $fractions; } } $question->category = $this->category->id; $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed) 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; } function readdata($filename) { /// Returns complete file with an array, one item per line if (is_readable($filename)) { $filearray = file($filename); /// Check for Macintosh OS line returns (ie file on one line), and fix if (ereg("\r", $filearray[0]) AND !ereg("\n", $filearray[0])) { return explode("\r", $filearray[0]); } else { return $filearray; } } return false; } function readquestions($lines) { /// Parses an array of lines into an array of questions, /// where each item is a question object as defined by /// readquestion(). Questions are defined as anything /// between blank lines. $questions = array(); $currentquestion = array(); foreach ($lines as $line) { $line = trim($line); if (empty($line)) { if (!empty($currentquestion)) { if ($question = $this->readquestion($currentquestion)) { $questions[] = $question; } $currentquestion = array(); } } else { $currentquestion[] = $line; } } if (!empty($currentquestion)) { // There may be a final question if ($question = $this->readquestion($currentquestion)) { $questions[] = $question; } } return $questions; } function defaultquestion() { // returns an "empty" question // Somewhere to specify question parameters that are not handled // by import but are required db fields. // This should not be overridden. $question = new stdClass(); $question->shuffleanswers = 0; $question->defaultgrade = 1; $question->image = ""; $question->usecase = 0; $question->multiplier = array(); return $question; } function readquestion($lines) { /// Given an array of lines known to define a question in /// this format, this function converts it into a question /// object suitable for processing and insertion into Moodle. $formatnotimplemented = get_string( 'formatnotimplemented','quiz' ); echo "

$formatnotimplemented

"; return NULL; } function importpostprocess() { /// Does any post-processing that may be desired /// Argument is a simple array of question ids that /// have just been added. return true; } // Export functions function export_file_extension() { /// return the files extension appropriate for this type /// override if you don't want .txt return ".txt"; } function exportpreprocess($category, $course) { /// Does any pre-processing that may be desired $this->category = $category; // Important $this->course = $course; // As is this! return true; } function presave_process( $content ) { /// enables any processing to be done on the content /// just prior to the file being saved /// default is to do nothing return $content; } function exportprocess($filename) { /// Exports a given category. There's probably little need to change this global $CFG; // create a directory for the exports (if not already existing) $dirname = get_string("exportfilename","quiz"); $courseid = $this->course->id; $path = $CFG->dataroot.'/'.$courseid.'/'.$dirname; if (!is_dir($path)) { if (!mkdir($path, $CFG->directorypermissions)) { error( get_string('cannotcreatepath','quiz',$path) ); } } // get the questions (from database) in this category // only get q's with no parents (no cloze subquestions specifically) $questions = get_questions_category( $this->category, true ); notify( get_string('exportingquestions','quiz') ); if (!count($questions)) { notify( get_string('noquestions','quiz') ); return false; } $count = 0; // results are first written into string (and then to a file) // so create/initialize the string here $expout = ""; // iterate through questions foreach($questions as $question) { $count++; $qtype = $question->qtype; // ignore random questiond if ($qtype!=RANDOM) { echo "

$count. ".stripslashes($question->questiontext)."

"; $expout .= $this->writequestion( $question ) . "\n"; } } // final pre-process on exported data $expout = $this->presave_process( $expout ); // write file $filepath = $path."/".$filename . $this->export_file_extension(); if (!$fh=fopen($filepath,"w")) { error( get_string('cannotopen','quiz',$filepath) ); } if (!fwrite($fh, $expout)) { error( get_string('cannotwrite','quiz',$filepath) ); } fclose($fh); return true; } function exportpostprocess() { /// Does any post-processing that may be desired return true; } function writequestion($question) { /// Turns a question object into textual output in the given format /// must be overidden // if not overidden, then this is an error. $formatnotimplemented = get_string( 'formatnotimplemented','quiz' ); echo "

$formatnotimplemented

"; return NULL; } } ?>