diff --git a/question/format/clozejr/format.php b/question/format/clozejr/format.php
new file mode 100644
index 00000000000..c44cc3bbabe
--- /dev/null
+++ b/question/format/clozejr/format.php
@@ -0,0 +1,470 @@
+libdir/xmlize.php" );
+ global $CFG, $langfile;
+ $langfile = $CFG->dirroot.'/question/format/clozejr/lang/';
+
+class qformat_clozejr extends qformat_default {
+ function provide_import() {
+ return false;
+ }
+ function provide_export() {
+ return true;
+ }
+
+ // IMPORT FUNCTIONS START HERE
+
+ function importprocess($lines) {
+ $questions = $this->readquestions($lines);
+ // Now process and store the unique cloze question
+ $question = $questions[0];
+ $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;
+ $question->course = '';
+ $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 import_text( $text ) {
+ $data = $text[0]['#'];
+ $data = html_entity_decode( $data );
+ return trim( $data );
+ }
+
+ function import_answer( $answer ) {
+ // import answer part of question
+
+ $fraction = $answer['@']['fraction'];
+ $text = $this->import_text( $answer['#']['text']);
+ $feedback = $this->import_text( $answer['#']['feedback'][0]['#']['text'] );
+
+ $ans = null;
+ $ans->answer = $text;
+ $ans->fraction = $fraction / 100;
+ $ans->feedback = $feedback;
+
+ return $ans;
+ }
+
+ function import_question( $question ) {
+ // run through the answers
+ $answers = $question['#']['answer'];
+ $an = '';
+ foreach ($answers as $answer) {
+ $ans = $this->import_answer( $answer );
+ $fraction = $ans->fraction * 100;
+ $an.="~%".$fraction."%".$ans->answer."#".$ans->feedback;
+ }
+ return $an;
+ }
+
+ function import_numerical( $question ) {
+ // import numerical question
+ // get answers array
+ $answers = $question['#']['answer'];
+ $an = '';
+ foreach ($answers as $answer) {
+ $fraction = trim($answer['#']['fraction'][0]['#']);
+ $ans = trim($answer['#'][0]);
+ $tolerance = trim($answer['#']['tolerance'][0]['#']);
+ $feedback = addslashes(trim(( $answer['#']['feedback'][0]['#']['text'][0]['#'] )));
+ $percent = $fraction * 100;
+ $an.="~%$percent%".$ans.":".$tolerance."#".$feedback;
+ }
+ return $an;
+ }
+
+ function reverse_strrchr($haystack, $needle)
+ {
+ $pos = strrpos($haystack, $needle);
+ if($pos === false) {
+ return $haystack;
+ }
+ return substr($haystack, 0, $pos + 0).'
';
+ }
+
+ function readquestions($lines) {
+ // this converts xml to big nasty data structure
+ // the 0 means keep white space as it is (important for markdown format)
+ // print_r it if you want to see what it looks like!
+ global $CFG, $langfile;
+ $xml = xmlize( $lines, 0 );
+ // set up array to hold all our questions
+ $questions = array();
+ $subquestions = array();
+ $clozequestionname = $xml['QUESTION_CATEGORY']['#']['NAME'][0]['#'];
+ notify(get_string( 'displayclozequestion','clozejr','',$langfile) );
+
+ // iterate through questions
+ $count = 0;
+ $numberthequestions = false;
+ foreach ($xml['QUESTION_CATEGORY']['#']['question'] as $question) {
+ $count++;
+ $questiontype = $question['@']['type'];
+ $an = null;
+ $defaultgrade = $question['#']['DEFAULTGRADE'][0]['#'];
+ switch($questiontype) {
+ CASE 'numerical' :
+ $an = $this->import_numerical( $question );
+ break;
+ CASE 'description' :
+ break;
+ CASE 'multichoice':
+ CASE 'regexp':
+ CASE 'shortanswer':
+ $an = addslashes( $this->import_question($question) );
+ break;
+ CASE 'matching' :
+ CASE 'cloze' :
+ default:
+ $an = null;
+ }
+ // stick the result in the $questions array
+ $isnewline = false;
+ if ($an OR ($questiontype == 'description')) {
+ //addslashes added JR 29 MAR 2007
+ $qtext = addslashes($this->import_text( $question['#']['questiontext'][0]['#']['text'] ) );
+ $qtext = ereg_replace("(?p>|?br ?/?>|\n)", "", $qtext);
+ // remove all
".stripslashes($qtext)."
"; + // print it here rather than in importprocess() + return $questions; + } + + // EXPORT FUNCTIONS START HERE + + function exportprocess() { + /// Exports a given category. There's probably little need to change this + global $CFG, $langfile; + + // create a directory for the exports (if not already existing) + if (! $export_dir = make_upload_directory($this->question_get_export_dir())) { + error( get_string('cannotcreatepath','quiz',$export_dir) ); + } + $path = $CFG->dataroot.'/'.$this->question_get_export_dir(); + + // 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('displayquestions', 'clozejr', '', $langfile) ); + + 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) { + // do not export hidden questions + if (!empty($question->hidden)) { + continue; + } + + // do not export questions of these types + $questiontype = $question->qtype; + $questiontypename = $this->get_qtype($questiontype); + if ($questiontype==RANDOM or $questiontype==MULTIANSWER or $questiontype==MATCH or $questiontype==TRUEFALSE or $questiontype==ESSAY or $questiontype==RANDOMSAMATCH) { + notify( get_string( 'clozetypeunsupported', 'clozejr', '', $langfile) ); + continue; + } + + // export the question displaying message + $count++; + $qtext = stripslashes($question->questiontext); + $qtext = ereg_replace("?p>", "", $qtext); + + echo "$count. ".$qtext."
"; + $expout .= $this->writequestion( $question ) . "\n"; + } + + // final pre-process on exported data + $expout = $this->presave_process( $expout ); + $result = $this->importprocess ($expout); + return true; + } + + function get_qtype( $type_id ) { + // translates question type code number into actual name + + switch( $type_id ) { + case TRUEFALSE: + $name = 'truefalse'; + break; + case MULTICHOICE: + $name = 'multichoice'; + break; + case SHORTANSWER: + $name = 'shortanswer'; + break; + case 'regexp': + $name = 'regexp'; + break; + case NUMERICAL: + $name = 'numerical'; + break; + case MATCH: + $name = 'matching'; + break; + case DESCRIPTION: + $name = 'description'; + break; + case ESSAY: + $name = 'essay'; + break; + case MULTIANSWER: + $name = 'cloze'; + break; + default: + $name = 'unknown'; + } + return $name; + } + + + function get_single( $id ) { + // translate single value into something sensible + + switch( $id ) { + case 0: + $name = "false"; + break; + case 1: + $name = "true"; + break; + default: + $name = "unknown"; + } + return $name; + } + + function writetext( $raw, $ilev=0, $short=true) { + // generates