]> git.mjollnir.org Git - moodle.git/commitdiff
Multianswer restore now works.
authorgustav_delius <gustav_delius>
Sat, 18 Mar 2006 14:14:55 +0000 (14:14 +0000)
committergustav_delius <gustav_delius>
Sat, 18 Mar 2006 14:14:55 +0000 (14:14 +0000)
Timelimit is rounded to integer before saving in the database
Some more diagnostic error messages
Towards more plugable question types: $QUIZ_MENU is now populated by the question types themselves.

16 files changed:
lib/questionlib.php
mod/quiz/lib.php
question/editlib.php
question/questiontypes/calculated/questiontype.php
question/questiontypes/description/questiontype.php
question/questiontypes/essay/questiontype.php
question/questiontypes/match/questiontype.php
question/questiontypes/multianswer/questiontype.php
question/questiontypes/multichoice/questiontype.php
question/questiontypes/numerical/questiontype.php
question/questiontypes/random/questiontype.php
question/questiontypes/randomsamatch/questiontype.php
question/questiontypes/rqp/questiontype.php
question/questiontypes/shortanswer/questiontype.php
question/questiontypes/truefalse/questiontype.php
question/restorelib.php

index d133da568fa16e7d35aa03bfd30451ea66eee591..7532245cf743242f4f82f6c57eebc53b5528fddc 100644 (file)
@@ -33,9 +33,7 @@ define('QUESTION_EVENTSUBMIT', '7');
 /**#@-*/
 
 /**#@+
-* The defined question types
-*
-* @todo It would be nicer to have a fully automatic plug-in system
+* The core question types
 */
 define("SHORTANSWER",   "1");
 define("TRUEFALSE",     "2");
@@ -59,14 +57,24 @@ define("QUESTION_NUMANS", "10");
 /**
 * Array holding question type objects
 */
-$QTYPES= array();
+global $QTYPES;
+$QTYPES = array(); // This array will be populated when the questiontype.php files are loaded
+
+/**
+* Array of question types names translated to the user's language
+*
+* The $QTYPE_MENU array holds the names of all the question types that the user should
+* be able to create directly. Some internal question types like random questions are excluded.
+* The complete list of question types can be found in {@link $QTYPES}.
+*/
+$QTYPE_MENU = array(); // This array will be populated when the questiontype.php files are loaded
 
 require_once("$CFG->dirroot/question/questiontypes/questiontype.php");
 
 /*
 * Load the questiontype.php file for each question type
 * These files in turn instantiate the corresponding question type class
-* and adds it to the $QTYPES array
+* and add them to the $QTYPES array
 */
 $qtypenames= get_list_of_plugins('question/questiontypes');
 foreach($qtypenames as $qtypename) {
@@ -156,7 +164,9 @@ class cmoptions {
 */
 function delete_question($question) {
     global $QTYPES;
-    $QTYPES[$question->qtype]->delete_question($question);
+    if (isset($QTYPES[$question->qtype])) {
+        $QTYPES[$question->qtype]->delete_question($question);
+    } else {echo 'qtype: '.$question->qtype.'<br />';}
     delete_records("question_answers", "question", $question->id);
     delete_records("question_states", "question", $question->id);
     delete_records("question_sessions", "questionid", $question->id);
index b4a0c491f6d590ce648c5e9614ff91a58206bf67..f133d8ac55a869818221c0519fd35537edab5dc5 100644 (file)
@@ -43,6 +43,8 @@ function quiz_add_instance($quiz) {
                                                     $quiz->availableminute);
     }
 
+    $quiz->timelimit = round($quiz->timelimit);
+
     if (empty($quiz->name)) {
         if (empty($quiz->intro)) {
             $quiz->name = get_string('modulename', 'quiz');
@@ -134,6 +136,8 @@ function quiz_update_instance($quiz) {
                                                     $quiz->availableminute);
     }
 
+    $quiz->timelimit = round($quiz->timelimit);
+
     $quiz->id = $quiz->instance;
 
     if (!update_record("quiz", $quiz)) {
@@ -268,7 +272,7 @@ function quiz_delete_instance($id) {
  */
 function quiz_delete_course($course, $feedback=true) {
 
-    global $CFG;
+    global $CFG, $QTYPES;
 
     //To detect if we have created the "container category"
     $concatid = 0;
index c6f7acf4f3230b45b7978789e9b9ddf3a6b006d0..5bf392bc921bb21a4aea23017e1931649b197ad2 100644 (file)
 
     require_once($CFG->libdir.'/questionlib.php');
 
-/**
-* Array of question types names translated to the user's language
-*
-* The $QTYPE_MENU array holds the names of all the question types that the user should
-* be able to create directly. Some internal question types like random questions are excluded.
-* The complete list of question types can be found in {@link $QTYPES}.
-*/
-
-$QTYPE_MENU = array ( MULTICHOICE   => get_string("multichoice", "quiz"),
-                              TRUEFALSE     => get_string("truefalse", "quiz"),
-                              SHORTANSWER   => get_string("shortanswer", "quiz"),
-                              NUMERICAL     => get_string("numerical", "quiz"),
-                              CALCULATED    => get_string("calculated", "quiz"),
-                              MATCH         => get_string("match", "quiz"),
-                              DESCRIPTION   => get_string("description", "quiz"),
-                              RANDOMSAMATCH => get_string("randomsamatch", "quiz"),
-                              MULTIANSWER   => get_string("multianswer", "quiz"),
-                              ESSAY         => get_string("essay", "quiz")
-                              );
-// add remote question types
-if ($rqp_types = get_records('question_rqp_types')) {
-    foreach($rqp_types as $type) {
-        $QTYPE_MENU[100+$type->id] = $type->name;
-    }
-}
 
 function question_category_form($course, $current, $recurse=1, $showhidden=false) {
     global $CFG;
index a2279cd6320071cf0f89cab93014ecb30c28b205..ca9374c00bb9342d39cbc0007b4e2d627aa8318a 100644 (file)
@@ -598,7 +598,10 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("CALCULATED",   "10"); // already defined in questionlib.php
 $QTYPES[CALCULATED]= new question_calculated_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[CALCULATED] = get_string("calculated", "quiz");
 
 function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
         $tolerance, $tolerancetype, $answerlength, $answerformat='1', $unit='') {
index 5e2bba129ee3d1d95b87cec6aed2ec623bf23efb..049ea3a5848aa18508f0aa8722ac280fe7e04338 100644 (file)
@@ -66,6 +66,9 @@ class quiz_description_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("DESCRIPTION",   "7"); // already defined in questionlib.php
 $QTYPES[DESCRIPTION]= new quiz_description_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[DESCRIPTION] = get_string("description", "quiz");
 
 ?>
index 9e02af48a3e0331b8e4259818d9ed4b9ab514679..c772ea1c7e0721c69f23a075c70d9b55882bf265 100644 (file)
@@ -311,6 +311,9 @@ class question_essay_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("ESSAY",        "12"); // already defined in questionlib.php
 $QTYPES[ESSAY] = new question_essay_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[ESSAY] = get_string("essay", "quiz");
 
 ?>
index 57a5285c07135ba062bc2abf58470f139d6500fa..91fdd12c03673125c82c872109937adc9598449a 100644 (file)
@@ -337,6 +337,9 @@ class question_match_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("MATCH",         "5"); // already defined in questionlib.php
 $QTYPES[MATCH]= new question_match_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[MATCH] = get_string("match", "quiz");
 
 ?>
index 8afc0249eb59880c8bddf28a9a99d14bd3f0d16c..e8c8460323ae1a20dcbcc1582ccc91e4c7ad0f40 100644 (file)
@@ -24,7 +24,7 @@ class quiz_embedded_cloze_qtype extends quiz_default_questiontype {
 
         // Get relevant data indexed by positionkey from the multianswers table
         if (!$sequence = get_field('question_multianswer', 'sequence', 'question', $question->id)) {
-            notify('Error: Missing question options!');
+            notify('Error: Cloze question '.$question->id.' is missing question options!');
             return false;
         }
 
@@ -92,13 +92,13 @@ class quiz_embedded_cloze_qtype extends quiz_default_questiontype {
              get_field('question_multianswer', 'id', 'question', $question->id)) {
                 $multianswer->id = $oldid;
                 if (!update_record("question_multianswer", $multianswer)) {
-                    $result->error = "Could not update quiz multianswer! " .
+                    $result->error = "Could not update cloze question options! " .
                      "(id=$multianswer->id)";
                     return $result;
                 }
             } else {
                 if (!insert_record("question_multianswer", $multianswer)) {
-                    $result->error = "Could not insert quiz multianswer!";
+                    $result->error = "Could not insert cloze question options!";
                     return $result;
                 }
             }
@@ -322,7 +322,7 @@ class quiz_embedded_cloze_qtype extends quiz_default_questiontype {
                    echo '</select>';
                    break;
                default:
-                   error("Unable to recognized questiontype ($wrapped->qtype) of
+                   error("Unable to recognize questiontype ($wrapped->qtype) of
                           question part $positionkey.");
                    break;
            }
@@ -380,8 +380,10 @@ class quiz_embedded_cloze_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("MULTIANSWER",   "9"); // already defined in questionlib.php
 $QTYPES[MULTIANSWER]= new quiz_embedded_cloze_qtype();
-
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[MULTIANSWER] = get_string("multianswer", "quiz");
 
 /////////////////////////////////////////////////////////////
 //// ADDITIONAL FUNCTIONS
index fa4ad22d8ed5b3ff3967bc37bf55e2a48fb6a128..5f14db95a1e92c7c2d056a3fc63512aa5a720d11 100644 (file)
@@ -372,6 +372,9 @@ class question_multichoice_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("MULTICHOICE",   "3"); // already defined in questionlib.php
 $QTYPES[MULTICHOICE]= new question_multichoice_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[MULTICHOICE] = get_string("multichoice", "quiz");
 
 ?>
index a5a53c16009b45e0ded832c0cd88796584bf9c31..a3919f7739f128bf156a490b98c166ab7755db43 100644 (file)
@@ -409,6 +409,9 @@ class question_numerical_qtype extends question_shortanswer_qtype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("NUMERICAL",     "8"); // already defined in questionlib.php
 $QTYPES[NUMERICAL]= new question_numerical_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[NUMERICAL] = get_string("numerical", "quiz");
 
 ?>
index d413aa2cecd280398a216faee6dc1443a1169353..697a6c43155287976668020867ff6fc969e84305 100644 (file)
@@ -237,6 +237,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("RANDOM",        "4"); // already defined in questionlib.php
 $QTYPES[RANDOM]= new quiz_random_qtype();
 
 ?>
index af53bf07f7e9b0c96f6fb88d53409f77110224b2..f73e729817d977e2d6090cd101f25b7a59a27e2a 100644 (file)
@@ -248,6 +248,9 @@ class question_randomsamatch_qtype extends question_match_qtype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("RANDOMSAMATCH", "6"); // already defined in questionlib.php
 $QTYPES[RANDOMSAMATCH]= new question_randomsamatch_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[RANDOMSAMATCH] = get_string("randomsamatch", "quiz");
 
 ?>
index 95e42e3c95d0dc3f142fb2f1a481968f27d99a19..119e58c552e379f98b5db6150b6aeece10a1f258 100644 (file)
@@ -437,6 +437,13 @@ class question_rqp_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("RQP",          "11"); // already defined in questionlib.php
 $QTYPES[RQP]= new question_rqp_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+if ($rqp_types = get_records('question_rqp_types')) {
+    foreach($rqp_types as $type) {
+        $QTYPE_MENU[100+$type->id] = $type->name;
+    }
+}
 
 ?>
index aa488cf9fba06adca88372b7403894f4fa5f5bc1..f96300559e1044fdc4bfa3458252220e6dffc47a 100644 (file)
@@ -246,6 +246,9 @@ class question_shortanswer_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("SHORTANSWER",   "1"); // already defined in questionlib.php
 $QTYPES[SHORTANSWER]= new question_shortanswer_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[SHORTANSWER] = get_string("shortanswer", "quiz");
 
 ?>
index 461136e747204399e19c95e6ee5687e8d5ccafa9..5b9076cb9dbb081a305e7864b5e1ecc02d233afe 100644 (file)
@@ -211,6 +211,9 @@ class question_truefalse_qtype extends quiz_default_questiontype {
 //////////////////////////////////////////////////////////////////////////
 //// INITIATION - Without this line the question type is not in use... ///
 //////////////////////////////////////////////////////////////////////////
+// define("TRUEFALSE",     "2"); // already defined in questionlib.php
 $QTYPES[TRUEFALSE]= new question_truefalse_qtype();
+// The following adds the questiontype to the menu of types shown to teachers
+$QTYPE_MENU[TRUEFALSE] = get_string("truefalse", "quiz");
 
 ?>
index 1c453f89b4fa12b4c2a3ace1c3866f4dd690fbd7..6862779a1fb0d4bcf9f100a971e92d56abf1712c 100644 (file)
     //-----------------------------------------------------------
 
     include_once($CFG->libdir.'/questionlib.php');
-    // load questiontype-specific functions
-    unset($restorefns);
-    unset($restoremapfns);
-    unset($restorestatefns);
-    unset($recodeansfns);
-    //if ($qtypes = get_records('question_types')) {
-    if ($qtypes = get_list_of_plugins('question/questiontypes')) {
-        foreach ($qtypes as $name) {
-            $qtype->name = $name;
-            $restorelib = $CFG->dirroot.'/question/questiontypes/'.$qtype->name.'/restorelib.php';
-            if (file_exists($restorelib)) {
-                include_once($restorelib);
-                $restorefn = 'question_'.$qtype->name.'_restore';
-                if (function_exists($restorefn)) {
-                    $restorefns[$qtype->name] = $restorefn;
-                }
-                $restoremapfn = 'question_'.$qtype->name.'_restore_map';
-                if (function_exists($restoremapfn)) {
-                    $restoremapfns[$qtype->name] = $restoremapfn;
-                }
-                $restorestatefn = 'question_'.$qtype->name.'_states_restore';
-                if (function_exists($restorestatefn)) {
-                    $restorestatefns[$qtype->name] = $restorestatefn;
-                }
-                $recodeansfn = 'question_'.$qtype->name.'_recode_answer';
-                if (function_exists($recodeansfn)) {
-                    $recodeansfns[$qtype->name] = $recodeansfn;
-                }
-            }
-        }
-    }
 
     function restore_question_categories($category,$restore) {
 
 
     function restore_questions ($old_category_id,$new_category_id,$info,$restore) {
 
-        global $CFG;
+        global $CFG, $QTYPES;
 
+        // load questiontype-specific functions
+        unset($restorefns);
+        unset($restoremapfns);
+        unset($recodeansfns);
+        foreach ($QTYPES as $key => $qtype) {
+            $restorelib = $CFG->dirroot.'/question/questiontypes/'.$qtype->name().'/restorelib.php';
+            if (file_exists($restorelib)) {
+                include_once($restorelib);
+                $restorefn = 'question_'.$qtype->name().'_restore';
+                if (function_exists($restorefn)) {
+                    $restorefns[$key] = $restorefn;
+                }else {echo $restorefn;}
+                $restoremapfn = 'question_'.$qtype->name().'_restore_map';
+                if (function_exists($restoremapfn)) {
+                    $restoremapfns[$key] = $restoremapfn;
+                }
+                $recodeansfn = 'question_'.$qtype->name().'_recode_answer';
+                if (function_exists($recodeansfn)) {
+                    $recodeansfns[$key] = $recodeansfn;
+                }
+            }
+        }
         $status = true;
         $restored_questions = array();
 
                 //Now, restore every question_answers in this question
                 $status = question_restore_answers($oldid,$newid,$que_info,$restore);
                 //Now, depending of the type of questions, invoke different functions
-                if (isset($restorefns[$question->type])) {
-                    $status = $restorefns[$question->type]->restore($oldid,$newid,$que_info,$restore);
+                if (isset($restorefns[$question->qtype])) {
+                    $status = $restorefns[$question->qtype]($oldid,$newid,$que_info,$restore);
                 }
             } else {
                 //We are NOT creating the question, but we need to know every question_answers
                 //Now, depending of the type of questions, invoke different functions
                 //to create the necessary mappings in backup_ids, because we are not
                 //creating the question, but need some records in backup table
-                if (isset($restoremapfns[$question->type])) {
-                    $status = $restoremapfns[$question->type]->restore($oldid,$newid,$que_info,$restore);
+                if (isset($restoremapfns[$question->qtype])) {
+                    $status = $restoremapfns[$question->qtype]($oldid,$newid,$que_info,$restore);
                 }
             }
 
             //We have to recode the answer field
             //It depends of the question type !!
             //We get the question first
-            $question = get_record("question","id",$state->question);
+            if (!$question = get_record("question","id",$state->question)) {
+                error("Can't find the record for question $state->question for which I am trying to restore a state");
+            }
             //It exists
             if ($question) {
-                //Depending of the qtype, we make different recodes
+                //Depending on the qtype, we make different recodes
                 switch ($question->qtype) {
                     case 1:    //SHORTANSWER QTYPE
                         //Nothing to do. The response is a text.
                         //Nothing to do. The response is a text.
                         break;
                     case 9:    //MULTIANSWER QTYPE
-                        //The answer is a comma separated list of hypen separated multianswer_id and answers. We must recode them.
+                        //The answer is a comma separated list of hypen separated sequence number and answers. We may have to recode the answers
                         $answer_field = "";
                         $in_first = true;
                         $tok = strtok($state->answer,",");
                         while ($tok) {
                             //Extract the multianswer_id and the answer
                             $exploded = explode("-",$tok);
-                            $multianswer_id = $exploded[0];
+                            $seqnum = $exploded[0];
                             $answer = $exploded[1];
-                            //Get the multianswer from backup_ids
-                            $mul = backup_getid($restore->backup_unique_code,"question_multianswer",$multianswer_id);
-                            if ($mul) {
-                                //Now, depending of the answertype field in question_multianswer
-                                //we do diferent things
-                                $mul_db = get_record ("question_multianswer","id",$mul->new_id);
-                                if ($mul_db->answertype == "1") {
-                                    //Shortanswer
-                                    //The answer is text, do nothing
-                                } else if ($mul_db->answertype == "3") {
-                                    //Multichoice
-                                    //The answer is an answer_id, look for it in backup_ids
-                                    $ans = backup_getid($restore->backup_unique_code,"question_answers",$answer);
-                                    $answer = $ans->new_id;
-                                } else if ($mul_db->answertype == "8") {
-                                    //Numeric
-                                    //The answer is text, do nothing
-                                }
-
-                                //Finaly, build the new answer field for each pair
-                                if ($in_first) {
-                                    $answer_field .= $mul->new_id."-".$answer;
-                                    $in_first = false;
-                                } else {
-                                    $answer_field .= ",".$mul->new_id."-".$answer;
-                                }
+                            // $sequence is an ordered array of the question ids.
+                            if (!$sequence = get_field('question_multianswer', 'sequence', 'question', $question->id)) {
+                                error("The cloze question $question->id is missing its options");
+                            }
+                            $sequence = explode(',', $sequence);
+                            // The id of the current question.
+                            $wrappedquestionid = $sequence[$seqnum-1];
+                            // now we can find the question
+                            if (!$wrappedquestion = get_record('question', 'id', $wrappedquestionid)) {
+                                error("Can't find the subquestion $wrappedquestionid that is used as part $seqnum in cloze question $question->id");
+                            }
+                            // For multichoice question we need to recode the answer
+                            if ($wrappedquestion->qtype == MULTICHOICE) {
+                                //The answer is an answer_id, look for it in backup_ids
+                                $ans = backup_getid($restore->backup_unique_code,"question_answers",$answer);
+                                $answer = $ans->new_id;
+                            }
+                            //build the new answer field for each pair
+                            if ($in_first) {
+                                $answer_field .= $seqnum."-".$answer;
+                                $in_first = false;
+                            } else {
+                                $answer_field .= ",".$seqnum."-".$answer;
                             }
                             //check for next
                             $tok = strtok(",");
                 backup_putid($restore->backup_unique_code,"question_states",$oldid,
                              $newid);
                 //Now process question type specific state information
-                foreach ($restorestatefns as $restorestatefn) {
-                    $restorestatefn($newid,$res_info,$restore);
+
+                if ($qtypes = get_list_of_plugins('question/questiontypes')) {
+                    foreach ($qtypes as $name) {
+                        $qtype->name = $name;
+                        $restorelib = $CFG->dirroot.'/question/questiontypes/'.$qtype->name.'/restorelib.php';
+                        if (file_exists($restorelib)) {
+                            include_once($restorelib);
+                            $restorestatefn = 'question_'.$qtype->name.'_states_restore';
+                            if (function_exists($restorestatefn)) {
+                                $restorestatefn($newid,$res_info,$restore);
+                            }
+                        }
+                    }
                 }
             } else {
                 $status = false;