/**#@-*/
/**#@+
-* 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");
/**
* 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) {
*/
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);
$quiz->availableminute);
}
+ $quiz->timelimit = round($quiz->timelimit);
+
if (empty($quiz->name)) {
if (empty($quiz->intro)) {
$quiz->name = get_string('modulename', 'quiz');
$quiz->availableminute);
}
+ $quiz->timelimit = round($quiz->timelimit);
+
$quiz->id = $quiz->instance;
if (!update_record("quiz", $quiz)) {
*/
function quiz_delete_course($course, $feedback=true) {
- global $CFG;
+ global $CFG, $QTYPES;
//To detect if we have created the "container category"
$concatid = 0;
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;
//////////////////////////////////////////////////////////////////////////
//// 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='') {
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
// 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;
}
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;
}
}
echo '</select>';
break;
default:
- error("Unable to recognized questiontype ($wrapped->qtype) of
+ error("Unable to recognize questiontype ($wrapped->qtype) of
question part $positionkey.");
break;
}
//////////////////////////////////////////////////////////////////////////
//// 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
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//////////////////////////////////////////////////////////////////////////
//// 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();
?>
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//////////////////////////////////////////////////////////////////////////
//// 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;
+ }
+}
?>
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//////////////////////////////////////////////////////////////////////////
//// 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");
?>
//-----------------------------------------------------------
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;