diff --git a/main/exercice/export/exercise_import.inc.php b/main/exercice/export/exercise_import.inc.php index 5ee82c5f0b..1dfcc62e60 100755 --- a/main/exercice/export/exercise_import.inc.php +++ b/main/exercice/export/exercise_import.inc.php @@ -13,37 +13,37 @@ /** * function to create a temporary directory (SAME AS IN MODULE ADMIN) */ +function tempdir($dir, $prefix = 'tmp', $mode = 0777) +{ + if (substr($dir, -1) != '/') { + $dir .= '/'; + } -function tempdir($dir, $prefix = 'tmp', $mode = 0777) { - if (substr($dir, -1) != '/') - $dir .= '/'; - - do { - $path = $dir . $prefix . mt_rand(0, 9999999); - } while (!mkdir($path, $mode)); + do { + $path = $dir . $prefix . mt_rand(0, 9999999); + } while (!mkdir($path, $mode)); - return $path; + return $path; } /** - * the path of the temporary directory where the exercise was uploaded and unzipped - * @param string + * Unzip the exercise in the temp folder + * @param string The path of the temporary directory where the exercise was uploaded and unzipped * @param string * @return bool */ - function get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath) { $_course = api_get_course_info(); $_user = api_get_user_info(); - //Check if the file is valid (not to big and exists) - if (!isset($_FILES['userFile']) || !is_uploaded_file($_FILES['userFile']['tmp_name'])) { - // upload failed - return false; - } + //Check if the file is valid (not to big and exists) + if (!isset($_FILES['userFile']) || !is_uploaded_file($_FILES['userFile']['tmp_name'])) { + // upload failed + return false; + } - if (preg_match('/.zip$/i', $_FILES['userFile']['name']) && + if (preg_match('/.zip$/i', $_FILES['userFile']['name']) && handle_uploaded_document( $_course, $_FILES['userFile'], @@ -55,93 +55,93 @@ function get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath) 1 ) ) { - return true; - } + return true; + } return false; } /** - * Imports an exercise, + * Imports an exercise in QTI format if the XML structure can be found in it * @param array $file * @return an array as a backlog of what was really imported, and error or debug messages to display */ - function import_exercise($file) { - global $exercise_info; - global $element_pile; - global $non_HTML_tag_to_avoid; - global $record_item_body; - // used to specify the question directory where files could be found in relation in any question - global $questionTempDir; - - $archive_path = api_get_path(SYS_ARCHIVE_PATH) . 'qti2'; - $baseWorkDir = $archive_path; - - if (!is_dir($baseWorkDir)) { - mkdir($baseWorkDir, api_get_permissions_for_new_directories(), true); - } + global $exercise_info; + global $element_pile; + global $non_HTML_tag_to_avoid; + global $record_item_body; + // used to specify the question directory where files could be found in relation in any question + global $questionTempDir; + + $archive_path = api_get_path(SYS_ARCHIVE_PATH) . 'qti2'; + $baseWorkDir = $archive_path; + + if (!is_dir($baseWorkDir)) { + mkdir($baseWorkDir, api_get_permissions_for_new_directories(), true); + } - $uploadPath = '/'; + $uploadPath = '/'; - // set some default values for the new exercise - $exercise_info = array (); - $exercise_info['name'] = preg_replace('/.zip$/i', '', $file); - $exercise_info['question'] = array(); - $element_pile = array (); + // set some default values for the new exercise + $exercise_info = array(); + $exercise_info['name'] = preg_replace('/.zip$/i', '', $file); + $exercise_info['question'] = array(); + $element_pile = array(); - // create parser and array to retrieve info from manifest - $element_pile = array (); //pile to known the depth in which we are - //$module_info = array (); //array to store the info we need + // create parser and array to retrieve info from manifest + $element_pile = array(); //pile to known the depth in which we are + //$module_info = array (); //array to store the info we need - // if file is not a .zip, then we cancel all + // if file is not a .zip, then we cancel all - if (!preg_match('/.zip$/i', $file)) { + if (!preg_match('/.zip$/i', $file)) { - return 'UplZipCorrupt'; - } + return 'UplZipCorrupt'; + } - // unzip the uploaded file in a tmp directory - if (!get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath)) { + // unzip the uploaded file in a tmp directory + if (!get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath)) { - return 'UplZipCorrupt'; - } + return 'UplZipCorrupt'; + } - // find the different manifests for each question and parse them. + // find the different manifests for each question and parse them. - $exerciseHandle = opendir($baseWorkDir); - //$question_number = 0; - $file_found = false; - $operation = false; + $exerciseHandle = opendir($baseWorkDir); + //$question_number = 0; + $file_found = false; + $operation = false; $result = false; $filePath = null; - // parse every subdirectory to search xml question files - while (false !== ($file = readdir($exerciseHandle))) { - - if (is_dir($baseWorkDir . '/' . $file) && $file != "." && $file != "..") { - // Find each manifest for each question repository found - $questionHandle = opendir($baseWorkDir . '/' . $file); - while (false !== ($questionFile = readdir($questionHandle))) { - if (preg_match('/.xml$/i', $questionFile)) { - $result = parse_file($baseWorkDir, $file, $questionFile); - $filePath = $baseWorkDir.$file; - $file_found = true; - } - } - } elseif (preg_match('/.xml$/i', $file)) { + // parse every subdirectory to search xml question files + while (false !== ($file = readdir($exerciseHandle))) { + + if (is_dir($baseWorkDir . '/' . $file) && $file != "." && $file != "..") { + + // Find each manifest for each question repository found + $questionHandle = opendir($baseWorkDir . '/' . $file); + while (false !== ($questionFile = readdir($questionHandle))) { + if (preg_match('/.xml$/i', $questionFile)) { + $result = parse_file($baseWorkDir, $file, $questionFile); + $filePath = $baseWorkDir . $file; + $file_found = true; + } + } + } elseif (preg_match('/.xml$/i', $file)) { // Else ignore file - $result = parse_file($baseWorkDir, '', $file); - $filePath = $baseWorkDir.'/'.$file; - $file_found = true; - } - } + $result = parse_file($baseWorkDir, '', $file); + $filePath = $baseWorkDir . '/' . $file; + $file_found = true; + } + } - if (!$file_found) { + if (!$file_found) { - return 'No XML file found in the zip'; - } + return 'No XML file found in the zip'; + } if ($result == false) { return false; @@ -151,61 +151,62 @@ function import_exercise($file) $doc->load($filePath); $encoding = $doc->encoding; - // 1. Create exercise. - $exercise = new Exercise(); - $exercise->exercise = $exercise_info['name']; - - $exercise->save(); - $last_exercise_id = $exercise->selectId(); - if (!empty($last_exercise_id)) { - // For each question found... - foreach ($exercise_info['question'] as $question_array) { - //2. Create question - $question = new Ims2Question(); - $question->type = $question_array['type']; - $question->setAnswer(); - $question->updateTitle(formatText($question_array['title'])); + // 1. Create exercise. + $exercise = new Exercise(); + $exercise->exercise = $exercise_info['name']; + + $exercise->save(); + $last_exercise_id = $exercise->selectId(); + if (!empty($last_exercise_id)) { + // For each question found... + foreach ($exercise_info['question'] as $question_array) { + //2. Create question + $question = new Ims2Question(); + $question->type = $question_array['type']; + $question->setAnswer(); + $question->updateTitle(formatText($question_array['title'])); //$question->updateDescription($question_array['title']); - $type = $question->selectType(); - $question->type = constant($type); - $question->save($last_exercise_id); - $last_question_id = $question->selectId(); - //3. Create answer - $answer = new Answer($last_question_id); - $answer->new_nbrAnswers = count($question_array['answer']); + $type = $question->selectType(); + $question->type = constant($type); + $question->save($last_exercise_id); + $last_question_id = $question->selectId(); + //3. Create answer + $answer = new Answer($last_question_id); + $answer->new_nbrAnswers = count($question_array['answer']); $totalCorrectWeight = 0; - foreach ($question_array['answer'] as $key => $answers) { - $split = explode('_', $key); - $i = $split[1]; + foreach ($question_array['answer'] as $key => $answers) { + $split = explode('_', $key); + $i = $split[1]; // Answer - $answer->new_answer[$i] = formatText($answers['value']); + $answer->new_answer[$i] = formatText($answers['value']); // Comment - $answer->new_comment[$i] = isset($answers['feedback']) ? formatText($answers['feedback']) : null; + $answer->new_comment[$i] = isset($answers['feedback']) ? formatText($answers['feedback']) : null; // Position - $answer->new_position[$i] = $i; - // Correct answers - if (in_array($key, $question_array['correct_answers'])) { - $answer->new_correct[$i] = 1; - } else { - $answer->new_correct[$i] = 0; - } - $answer->new_weighting[$i] = $question_array['weighting'][$key]; + $answer->new_position[$i] = $i; + // Correct answers + if (in_array($key, $question_array['correct_answers'])) { + $answer->new_correct[$i] = 1; + } else { + $answer->new_correct[$i] = 0; + } + $answer->new_weighting[$i] = $question_array['weighting'][$key]; if ($answer->new_correct[$i]) { $totalCorrectWeight = $answer->new_weighting[$i]; } - } + } $question->updateWeighting($totalCorrectWeight); $question->save($last_exercise_id); - $answer->save(); - } + $answer->save(); + } - // delete the temp dir where the exercise was unzipped - my_delete($baseWorkDir . $uploadPath); - return $last_exercise_id; - } + // delete the temp dir where the exercise was unzipped + my_delete($baseWorkDir . $uploadPath); + return $last_exercise_id; + } - return false; + return false; } + /** * We assume the file charset is UTF8 **/ @@ -214,163 +215,156 @@ function formatText($text) return api_html_entity_decode($text); } +/** + * Parses a given XML file and fills global arrays with the elements + * @param $exercisePath + * @param $file + * @param $questionFile + * @return bool + */ function parse_file($exercisePath, $file, $questionFile) { - global $exercise_info; - global $element_pile; - global $non_HTML_tag_to_avoid; - global $record_item_body; - global $questionTempDir; - - $questionTempDir = $exercisePath . '/' . $file . '/'; - $questionFilePath = $questionTempDir . $questionFile; - - if (!($fp = fopen($questionFilePath, 'r'))) { - Display :: display_error_message(get_lang('Error opening question\'s XML file')); - return false; - } else { - $data = fread($fp, filesize($questionFilePath)); - } - - //parse XML question file - $data = str_replace(array('

', '

','',''), '', $data); - - //used global variable start values declaration : - - $record_item_body = false; - $non_HTML_tag_to_avoid = array ( - "SIMPLECHOICE", - "CHOICEINTERACTION", - "INLINECHOICEINTERACTION", - "INLINECHOICE", - "SIMPLEMATCHSET", - "SIMPLEASSOCIABLECHOICE", - "TEXTENTRYINTERACTION", - "FEEDBACKINLINE", - "MATCHINTERACTION", - "ITEMBODY", - "BR", - "IMG" - ); - - //this array to detect tag not supported by claroline import in the xml file to warn the user. - - $non_supported_content_in_question = array ( - "GAPMATCHINTERACTION", - "EXTENDEDTEXTINTERACTION", - "HOTTEXTINTERACTION", - "HOTSPOTINTERACTION", - "SELECTPOINTINTERACTION", - "GRAPHICORDERINTERACTION", - "GRAPHICASSOCIATIONINTERACTION", - "GRAPHICGAPMATCHINTERACTION", - "POSITIONOBJECTINTERACTION", - "SLIDERINTERACTION", - "DRAWINGINTERACTION", - "UPLOADINTERACTION", - "RESPONSECONDITION", - "RESPONSEIF" - ); + global $non_HTML_tag_to_avoid; + global $record_item_body; + global $questionTempDir; + + $questionTempDir = $exercisePath . '/' . $file . '/'; + $questionFilePath = $questionTempDir . $questionFile; + + if (!($fp = fopen($questionFilePath, 'r'))) { + Display:: display_error_message(get_lang('Error opening question\'s XML file')); + return false; + } else { + $data = fread($fp, filesize($questionFilePath)); + } + + //parse XML question file + $data = str_replace(array('

', '

', '', ''), '', $data); + + //used global variable start values declaration : + + $record_item_body = false; + $non_HTML_tag_to_avoid = array( + "SIMPLECHOICE", + "CHOICEINTERACTION", + "INLINECHOICEINTERACTION", + "INLINECHOICE", + "SIMPLEMATCHSET", + "SIMPLEASSOCIABLECHOICE", + "TEXTENTRYINTERACTION", + "FEEDBACKINLINE", + "MATCHINTERACTION", + "ITEMBODY", + "BR", + "IMG" + ); $question_format_supported = true; - $xml_parser = xml_parser_create(); - xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, false); - xml_set_element_handler($xml_parser, 'startElement', 'endElement'); - xml_set_character_data_handler($xml_parser, 'elementData'); - if (!xml_parse($xml_parser, $data, feof($fp))) { - // if reading of the xml file in not successful : - // set errorFound, set error msg, break while statement - Display :: display_error_message(get_lang('Error reading XML file')); - return false; - } - - //close file - fclose($fp); - if (!$question_format_supported) { - Display :: display_error_message(get_lang('Unknown question format in file %file', array ( - '%file' => $questionFile - ))); - return false; - } - return true; + $xml_parser = xml_parser_create(); + xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, false); + xml_set_element_handler($xml_parser, 'startElement', 'endElement'); + xml_set_character_data_handler($xml_parser, 'elementData'); + if (!xml_parse($xml_parser, $data, feof($fp))) { + // if reading of the xml file in not successful : + // set errorFound, set error msg, break while statement + Display:: display_error_message(get_lang('Error reading XML file')); + return false; + } + + //close file + fclose($fp); + if (!$question_format_supported) { + Display:: display_error_message( + get_lang( + 'Unknown question format in file %file', + array( + '%file' => $questionFile + ) + ) + ); + return false; + } + return true; } /** * Function used by the SAX xml parser when the parser meets a opening tag * - * @param unknown_type $parser xml parser created with "xml_parser_create()" - * @param unknown_type $name name of the element - * @param unknown_type $attributes + * @param object $parser xml parser created with "xml_parser_create()" + * @param string $name name of the element + * @param array $attributes */ +function startElement($parser, $name, $attributes) +{ + global $element_pile; + global $exercise_info; + global $current_question_ident; + global $current_answer_id; + global $current_match_set; + global $currentAssociableChoice; + global $current_question_item_body; + global $record_item_body; + global $non_HTML_tag_to_avoid; + global $current_inlinechoice_id; + global $cardinality; + global $questionTempDir; + + array_push($element_pile, $name); + $current_element = end($element_pile); + if (sizeof($element_pile) >= 2) { + $parent_element = $element_pile[sizeof($element_pile) - 2]; + } else { + $parent_element = ""; + } + if (sizeof($element_pile) >= 3) { + $grant_parent_element = $element_pile[sizeof($element_pile) - 3]; + } else { + $grant_parent_element = ""; + } + + if ($record_item_body) { -function startElement($parser, $name, $attributes) { - global $element_pile; - global $exercise_info; - global $current_question_ident; - global $current_answer_id; - global $current_match_set; - global $currentAssociableChoice; - global $current_question_item_body; - global $record_item_body; - global $non_HTML_tag_to_avoid; - global $current_inlinechoice_id; - global $cardinality; - global $questionTempDir; - - array_push($element_pile, $name); - $current_element = end($element_pile); - if (sizeof($element_pile) >= 2) - $parent_element = $element_pile[sizeof($element_pile) - 2]; - else - $parent_element = ""; - if (sizeof($element_pile) >= 3) - $grant_parent_element = $element_pile[sizeof($element_pile) - 3]; - else - $grant_parent_element = ""; - - if ($record_item_body) { - - if ((!in_array($current_element, $non_HTML_tag_to_avoid))) { - $current_question_item_body .= "<" . $name; - - foreach ($attributes as $attribute_name => $attribute_value) { - $current_question_item_body .= " " . $attribute_name . "=\"" . $attribute_value . "\""; - } - $current_question_item_body .= ">"; - } else { - //in case of FIB question, we replace the IMS-QTI tag b y the correct answer between "[" "]", - //we first save with claroline tags ,then when the answer will be parsed, the claroline tags will be replaced - - if ($current_element == 'INLINECHOICEINTERACTION') { - - $current_question_item_body .= "**claroline_start**" . $attributes['RESPONSEIDENTIFIER'] . "**claroline_end**"; - } - if ($current_element == 'TEXTENTRYINTERACTION') { - $correct_answer_value = $exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id]; - $current_question_item_body .= "[" . $correct_answer_value . "]"; - - } - if ($current_element == 'BR') { - $current_question_item_body .= "
"; - } - } - } - switch ($current_element) { - case 'ASSESSMENTITEM' : + if ((!in_array($current_element, $non_HTML_tag_to_avoid))) { + $current_question_item_body .= "<" . $name; + + foreach ($attributes as $attribute_name => $attribute_value) { + $current_question_item_body .= " " . $attribute_name . "=\"" . $attribute_value . "\""; + } + $current_question_item_body .= ">"; + } else { + //in case of FIB question, we replace the IMS-QTI tag b y the correct answer between "[" "]", + //we first save with claroline tags ,then when the answer will be parsed, the claroline tags will be replaced + + if ($current_element == 'INLINECHOICEINTERACTION') { + + $current_question_item_body .= "**claroline_start**" . $attributes['RESPONSEIDENTIFIER'] . "**claroline_end**"; + } + if ($current_element == 'TEXTENTRYINTERACTION') { + $correct_answer_value = $exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id]; + $current_question_item_body .= "[" . $correct_answer_value . "]"; + + } + if ($current_element == 'BR') { + $current_question_item_body .= "
"; + } + } + } + switch ($current_element) { + case 'ASSESSMENTITEM': //retrieve current question $current_question_ident = $attributes['IDENTIFIER']; - $exercise_info['question'][$current_question_ident] = array (); - $exercise_info['question'][$current_question_ident]['answer'] = array (); - $exercise_info['question'][$current_question_ident]['correct_answers'] = array (); + $exercise_info['question'][$current_question_ident] = array(); + $exercise_info['question'][$current_question_ident]['answer'] = array(); + $exercise_info['question'][$current_question_ident]['correct_answers'] = array(); $exercise_info['question'][$current_question_ident]['title'] = $attributes['TITLE']; $exercise_info['question'][$current_question_ident]['tempdir'] = $questionTempDir; break; - case 'SECTION': + case 'SECTION': //retrieve exercise name $exercise_info['name'] = $attributes['TITLE']; - break; - case 'RESPONSEDECLARATION': + break; + case 'RESPONSEDECLARATION': // Retrieve question type if ("multiple" == $attributes['CARDINALITY']) { $exercise_info['question'][$current_question_ident]['type'] = 'MCMA'; @@ -382,64 +376,64 @@ function startElement($parser, $name, $attributes) { } //needed for FIB $current_answer_id = $attributes['IDENTIFIER']; - break; - case 'INLINECHOICEINTERACTION' : + break; + case 'INLINECHOICEINTERACTION': $exercise_info['question'][$current_question_ident]['type'] = 'FIB'; - $exercise_info['question'][$current_question_ident]['subtype'] = 'LISTBOX_FILL'; - $current_answer_id = $attributes['RESPONSEIDENTIFIER']; - break; - case 'INLINECHOICE' : + $exercise_info['question'][$current_question_ident]['subtype'] = 'LISTBOX_FILL'; + $current_answer_id = $attributes['RESPONSEIDENTIFIER']; + break; + case 'INLINECHOICE': $current_inlinechoice_id = $attributes['IDENTIFIER']; - break; - case 'TEXTENTRYINTERACTION': + break; + case 'TEXTENTRYINTERACTION': $exercise_info['question'][$current_question_ident]['type'] = 'FIB'; $exercise_info['question'][$current_question_ident]['subtype'] = 'TEXTFIELD_FILL'; $exercise_info['question'][$current_question_ident]['response_text'] = $current_question_item_body; //replace claroline tags - break; - case 'MATCHINTERACTION': - $exercise_info['question'][$current_question_ident]['type'] = 'MATCHING'; - break; - case 'SIMPLEMATCHSET' : + break; + case 'MATCHINTERACTION': + $exercise_info['question'][$current_question_ident]['type'] = 'MATCHING'; + break; + case 'SIMPLEMATCHSET': if (!isset ($current_match_set)) { $current_match_set = 1; } else { $current_match_set++; } - $exercise_info['question'][$current_question_ident]['answer'][$current_match_set] = array (); - break; - case 'SIMPLEASSOCIABLECHOICE': + $exercise_info['question'][$current_question_ident]['answer'][$current_match_set] = array(); + break; + case 'SIMPLEASSOCIABLECHOICE': $currentAssociableChoice = $attributes['IDENTIFIER']; - break; - //retrieve answers id for MCUA and MCMA questions - case 'SIMPLECHOICE': + break; + //retrieve answers id for MCUA and MCMA questions + case 'SIMPLECHOICE': $current_answer_id = $attributes['IDENTIFIER']; if (!isset($exercise_info['question'][$current_question_ident]['answer'][$current_answer_id])) { - $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id] = array (); + $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id] = array(); } - break; - case 'MAPENTRY': + break; + case 'MAPENTRY': if ($parent_element == "MAPPING") { $answer_id = $attributes['MAPKEY']; if (!isset ($exercise_info['question'][$current_question_ident]['weighting'])) { - $exercise_info['question'][$current_question_ident]['weighting'] = array (); + $exercise_info['question'][$current_question_ident]['weighting'] = array(); } $exercise_info['question'][$current_question_ident]['weighting'][$answer_id] = $attributes['MAPPEDVALUE']; } - break; - case 'MAPPING': + break; + case 'MAPPING': if (isset ($attributes['DEFAULTVALUE'])) { $exercise_info['question'][$current_question_ident]['default_weighting'] = $attributes['DEFAULTVALUE']; } - case 'ITEMBODY': + case 'ITEMBODY': $record_item_body = true; $current_question_item_body = ''; - break; - case 'IMG': + break; + case 'IMG': $exercise_info['question'][$current_question_ident]['attached_file_url'] = $attributes['SRC']; - break; - } + break; + } } /** @@ -448,87 +442,93 @@ function startElement($parser, $name, $attributes) { * @param $parser xml parser created with "xml_parser_create()" * @param $name name of the element */ +function endElement($parser, $name) +{ + global $element_pile; + global $exercise_info; + global $current_question_ident; + global $record_item_body; + global $current_question_item_body; + global $non_HTML_tag_to_avoid; + global $cardinality; -function endElement($parser, $name) { - global $element_pile; - global $exercise_info; - global $current_question_ident; - global $record_item_body; - global $current_question_item_body; - global $non_HTML_tag_to_avoid; - global $cardinality; - - $current_element = end($element_pile); + $current_element = end($element_pile); - //treat the record of the full content of itembody tag : + //treat the record of the full content of itembody tag : - if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) { - $current_question_item_body .= ""; - } + if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) { + $current_question_item_body .= ""; + } - switch ($name) { - case 'ITEMBODY': + switch ($name) { + case 'ITEMBODY': $record_item_body = false; if ($exercise_info['question'][$current_question_ident]['type'] == 'FIB') { $exercise_info['question'][$current_question_ident]['response_text'] = $current_question_item_body; } else { $exercise_info['question'][$current_question_ident]['statement'] = $current_question_item_body; } - break; - } - array_pop($element_pile); + break; + } + array_pop($element_pile); } -function elementData($parser, $data) { - - global $element_pile; - global $exercise_info; - global $current_question_ident; - global $current_answer_id; - global $current_match_set; - global $currentAssociableChoice; - global $current_question_item_body; - global $record_item_body; - global $non_HTML_tag_to_avoid; - global $current_inlinechoice_id; - global $cardinality; - - $current_element = end($element_pile); - if (sizeof($element_pile) >= 2) - $parent_element = $element_pile[sizeof($element_pile) - 2]; - else - $parent_element = ""; - if (sizeof($element_pile) >= 3) - $grant_parent_element = $element_pile[sizeof($element_pile) - 3]; - else - $grant_parent_element = ""; - - //treat the record of the full content of itembody tag (needed for question statment and/or FIB text: - - if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) { - $current_question_item_body .= $data; - } - - switch ($current_element) { - case 'SIMPLECHOICE': +/** + * @param $parser + * @param $data + */ +function elementData($parser, $data) +{ + global $element_pile; + global $exercise_info; + global $current_question_ident; + global $current_answer_id; + global $current_match_set; + global $currentAssociableChoice; + global $current_question_item_body; + global $record_item_body; + global $non_HTML_tag_to_avoid; + global $current_inlinechoice_id; + global $cardinality; + + $current_element = end($element_pile); + if (sizeof($element_pile) >= 2) { + $parent_element = $element_pile[sizeof($element_pile) - 2]; + } else { + $parent_element = ""; + } + if (sizeof($element_pile) >= 3) { + $grant_parent_element = $element_pile[sizeof($element_pile) - 3]; + } else { + $grant_parent_element = ""; + } + + //treat the record of the full content of itembody tag (needed for question statment and/or FIB text: + + if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) { + $current_question_item_body .= $data; + } + + switch ($current_element) { + case 'SIMPLECHOICE': if (!isset ($exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'])) { $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'] = trim($data); } else { - $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'] .= ''.trim($data); + $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'] .= '' . trim($data); } - break; - case 'FEEDBACKINLINE' : + break; + case 'FEEDBACKINLINE': if (!isset ($exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['feedback'])) { $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['feedback'] = trim($data); } else { $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['feedback'] .= ' ' . trim($data); } - break; - case 'SIMPLEASSOCIABLECHOICE': - $exercise_info['question'][$current_question_ident]['answer'][$current_match_set][$currentAssociableChoice] = trim($data); - break; - case 'VALUE' : + break; + case 'SIMPLEASSOCIABLECHOICE': + $exercise_info['question'][$current_question_ident]['answer'][$current_match_set][$currentAssociableChoice] = trim($data); + break; + case 'VALUE': if ($parent_element == "CORRECTRESPONSE") { if ($cardinality == "single") { $exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id] = $data; @@ -536,22 +536,26 @@ function elementData($parser, $data) { $exercise_info['question'][$current_question_ident]['correct_answers'][] = $data; } } - break; + break; - case 'ITEMBODY' : + case 'ITEMBODY': $current_question_item_body .= $data; - break; - case 'INLINECHOICE' : + break; + case 'INLINECHOICE': // if this is the right answer, then we must replace the claroline tags in the FIB text bye the answer between "[" and "]" : $answer_identifier = $exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id]; if ($current_inlinechoice_id == $answer_identifier) { - $current_question_item_body = str_replace("**claroline_start**" . $current_answer_id . "**claroline_end**", "[" . $data . "]", $current_question_item_body); + $current_question_item_body = str_replace( + "**claroline_start**" . $current_answer_id . "**claroline_end**", + "[" . $data . "]", + $current_question_item_body + ); } else { if (!isset ($exercise_info['question'][$current_question_ident]['wrong_answers'])) { - $exercise_info['question'][$current_question_ident]['wrong_answers'] = array (); + $exercise_info['question'][$current_question_ident]['wrong_answers'] = array(); } $exercise_info['question'][$current_question_ident]['wrong_answers'][] = $data; } - break; - } + break; + } } diff --git a/main/exercice/export/exercise_import.php b/main/exercice/export/exercise_import.php index ca705c73ff..72048868a0 100755 --- a/main/exercice/export/exercise_import.php +++ b/main/exercice/export/exercise_import.php @@ -25,7 +25,6 @@ require_once api_get_path(LIBRARY_PATH) . 'fileUpload.lib.php'; require_once 'exercise_import.inc.php'; include_once '../exercise.class.php'; include_once '../question.class.php'; -include_once 'qti/qti_classes.php'; //SQL table name diff --git a/main/exercice/export/qti/qti_classes.php b/main/exercice/export/qti/qti_classes.php deleted file mode 100755 index 5a9f9950d4..0000000000 --- a/main/exercice/export/qti/qti_classes.php +++ /dev/null @@ -1,578 +0,0 @@ - - * @author Yannick Warnier - * @package chamilo.exercise - */ -/** - * Code - */ -if ( count( get_included_files() ) == 1 ) die( '---' ); -require_once '../../exercise.class.php'; -require_once '../../question.class.php'; -require_once '../../answer.class.php'; -require_once '../../unique_answer.class.php'; -require_once '../../multiple_answer.class.php'; -require_once '../../fill_blanks.class.php'; -require_once '../../freeanswer.class.php'; -require_once '../../hotspot.class.php'; -require_once '../../matching.class.php'; -require_once '../../hotspot.class.php'; - - -/** - * - * @package chamilo.exercise - */ -class ImsQuestion extends Question -{ - /** - * Include the correct answer class and create answer - */ - function setAnswer() - { - switch($this->type) - { - case MCUA : - $this->answer = new ImsAnswerMultipleChoice($this->id, false); - break; - case MCMA : - $this->answer = new ImsAnswerMultipleChoice($this->id, true); - break; - case TF : - $this->answer = new ImsAnswerTrueFalse($this->id); - break; - case FIB : - $this->answer = new ImsAnswerFillInBlanks($this->id); - break; - case MATCHING : - $this->answer = new ImsAnswerMatching($this->id); - break; - default : - $this->answer = null; - break; - } - - return true; - } - - /** - * allow to import the question - * - * @param questionArray is an array that must contain all the information needed to build the question - * @author Guillaume Lederer - */ - - function import($questionArray, $exerciseTempPath) - { - //import answers - - $this->answer->import($questionArray); - - //import attached file, if any - - if (isset($questionArray['attached_file_url'])) - { - $file= array(); - $file['name'] = $questionArray['attached_file_url']; - $file['tmp_name'] = $exerciseTempPath.$file['name']; - - $this->setAttachment($file); - } - } -} - -/** - * - * @package chamilo.exercise - */ -class ImsAnswerMultipleChoice extends answerMultipleChoice -{ - /** - * Return the XML flow for the possible answers. - * That's one , containing several - * - * @author Amand Tihon - */ - function imsExportResponses($questionIdent) - { - // Opening of the response block. - if( $this->multipleAnswer ) - { - $out = '' . "\n" - . '' . "\n"; - } - else - { - $out = '' . "\n"; - } - - // Loop over answers - foreach( $this->answerList as $answer ) - { - $responseIdent = $questionIdent . "_A_" . $answer['id']; - - $out.= ' '.(!$this->multipleAnswer ? '':'').'' . "\n" - . ' ' . "\n" - . ' '.(!$this->multipleAnswer ? '':'').'' . "\n"; - } - $out.= "\n"; - - return $out; - } - - /** - * Return the XML flow of answer processing : a succession of . - * - * @author Amand Tihon - */ - function imsExportProcessing($questionIdent) - { - $out = ''; - - foreach( $this->answerList as $answer ) - { - $responseIdent = $questionIdent . "_A_" . $answer['id']; - $feedbackIdent = $questionIdent . "_F_" . $answer['id']; - $conditionIdent = $questionIdent . "_C_" . $answer['id']; - - if( $this->multipleAnswer ) - { - $out .= '' . "\n" - . ' ' . $responseIdent . '' . "\n"; - } - else - { - $out .= '' . "\n" - . ' ' . $responseIdent . '' . "\n"; - } - - $out .= " \n" . ' ' . $answer['grade'] . "\n"; - - // Only add references for actually existing comments/feedbacks. - if( !empty($answer['comment']) ) - { - $out .= ' ' . "\n"; - } - $out .= "\n"; - } - return $out; - } - - /** - * Export the feedback (comments to selected answers) to IMS/QTI - * - * @author Amand Tihon - */ - function imsExportFeedback($questionIdent) - { - $out = ""; - foreach( $this->answerList as $answer ) - { - if( !empty($answer['comment']) ) - { - $feedbackIdent = $questionIdent . "_F_" . $answer['id']; - $out.= '' . "\n" - . ' \n" - . "\n"; - } - } - return $out; - } - - /** - * allow to import the answers, feedbacks, and grades of a question - * @param questionArray is an array that must contain all the information needed to build the question - * @author Guillaume Lederer - */ - - function import($questionArray) - { - - $answerArray = $questionArray['answer']; - - $this->answerList = array(); //re-initialize answer object content - - - - foreach ($answerArray as $key => $answer) - { - if (!isset($answer['feedback'])) $answer['feedback'] = ""; - if (!isset($questionArray['weighting'][$key])) - { - if (isset($questionArray['default_weighting'])) - { - $grade = $questionArray['default_weighting']; - } - else - { - $grade = 0; - } - } - else - { - $grade = $questionArray['weighting'][$key]; - } - if (in_array($key,$questionArray['correct_answers'])) $is_correct = true; else $is_correct = false; - $addedAnswer = array( - 'answer' => $answer['value'], - 'correct' => $is_correct, - 'grade' => $grade, - 'comment' => $answer['feedback'], - ); - - $this->answerList[] = $addedAnswer; - } - } -} - -/** - * - * @package chamilo.exercise - */ -class ImsAnswerTrueFalse extends answerTrueFalse -{ - /** - * Return the XML flow for the possible answers. - * That's one , containing several - * - * @author Amand Tihon - */ - function imsExportResponses($questionIdent) - { - // Opening of the response block. - $out = '' . "\n"; - - // true - $response_ident = $questionIdent . '_A_true'; - $out .= - ' ' . "\n" - . ' ' . "\n" - . ' ' . "\n"; - - // false - $response_ident = $questionIdent . '_A_false'; - $out .= - ' ' . "\n" - . ' ' . "\n" - . ' ' . "\n"; - - $out .= '' . "\n"; - - return $out; - } - - /** - * Return the XML flow of answer processing : a succession of . - * - * @author Amand Tihon - */ - function imsExportProcessing($questionIdent) - { - $out = ''; - - // true - $response_ident = $questionIdent. '_A_true'; - $feedback_ident = $questionIdent . '_F_true'; - $condition_ident = $questionIdent . '_C_true'; - - $out .= - '' . "\n" - . ' ' . $response_ident . '' . "\n" - . ' ' . "\n" . ' ' . $this->trueGrade . '' . "\n"; - - // Only add references for actually existing comments/feedbacks. - if( !empty($this->trueFeedback) ) - { - $out.= ' ' . "\n"; - } - - $out .= '' . "\n"; - - // false - $response_ident = $questionIdent. '_A_false'; - $feedback_ident = $questionIdent . '_F_false'; - $condition_ident = $questionIdent . '_C_false'; - - $out .= - '' . "\n" - . ' ' . $response_ident . '' . "\n" - . ' ' . "\n" . ' ' . $this->falseGrade . '' . "\n"; - - // Only add references for actually existing comments/feedbacks. - if( !empty($this->falseFeedback) ) - { - $out.= ' ' . "\n"; - } - - $out .= '' . "\n"; - - return $out; - } - - /** - * Export the feedback (comments to selected answers) to IMS/QTI - * - * @author Amand Tihon - */ - function imsExportFeedback($questionIdent) - { - $out = ""; - - if( !empty($this->trueFeedback) ) - { - $feedback_ident = $questionIdent . '_F_true'; - $out.= '' . "\n" - . ' trueFeedback . "]]>\n" - . "\n"; - } - - if( !empty($this->falseFeedback) ) - { - $feedback_ident = $questionIdent . '_F_false'; - $out.= '' . "\n" - . ' falseFeedback . "]]>\n" - . "\n"; - } - return $out; - } -} - -/** - * - * @package chamilo.exercise - */ -class ImsAnswerFillInBlanks extends answerFillInBlanks -{ - /** - * Export the text with missing words. - * - * As a side effect, it stores two lists in the class : - * the missing words and their respective weightings. - * - * @author Amand Tihon - */ - function imsExportResponses($questionIdent) - { - global $charset; - - $out = "\n"; - - $responsePart = explode(']', $this->answer); - $i = 0; // Used for the reference generation. - foreach($responsePart as $part) - { - $response_ident = $questionIdent . "_A_" . $i; - - if( strpos($part,'[') !== false ) - { - list($rawText, $blank) = explode('[', $part); - } - else - { - $rawText = $part; - $blank = ""; - } - - if ($rawText!="") - { - $out.=" \n"; - } - - if ($blank!="") - { - $out.= ' ' . "\n" - . ' ' . "\n" - . ' ' . "\n" - . " \n" - . " \n"; - } - $i++; - } - $out.="\n"; - - return $out; - - } - - /** - * Exports the response processing. - * - * It uses the two lists build by export_responses(). This implies that export_responses MUST - * be called before. - * - * @author Amand Tihon - */ - function imsExportProcessing($questionIdent) - { - $out = ""; - - $answerCount = count($this->answerList); - - for( $i = 0; $i < $answerCount ; $i++ ) - { - $response_ident = $questionIdent . "_A_" . $i; - $out.= ' ' . "\n" - . ' answerList[$i] . ']]>' . "\n" - . ' ' . $this->gradeList[$i] . "\n" - . " \n"; - } - return $out; - } - - /** - * Export the feedback (comments to selected answers) to IMS/QTI - * - * @author Amand Tihon - */ - function imsExportFeedback($questionIdent) - { - // no feedback in this question type - return ''; - } - - /** - * allow to import the answers, feedbacks, and grades of a question - * - * @param questionArray is an array that must contain all the information needed to build the question - * @author Guillaume Lederer - */ - - function import($questionArray) - { - $answerArray = $questionArray['answer']; - $this->answerText = str_replace ("\n","",$questionArray['response_text']); - if ($questionArray['subtype'] == "TEXTFIELD_FILL") $this->type = TEXTFIELD_FILL; - if ($questionArray['subtype'] == "LISTBOX_FILL") - { - $this->wrongAnswerList = $questionArray['wrong_answers']; - $this->type = LISTBOX_FILL; - } - - //build correct_answsers array - - if (isset($questionArray['weighting'])) - { - $this->gradeList = $questionArray['weighting']; - } - } -} - -/** - * - * @package chamilo.exercise - */ -class ImsAnswerMatching extends answerMatching -{ - /** - * Export the question part as a matrix-choice, with only one possible answer per line. - * @author Amand Tihon - */ - function imsExportResponses($questionIdent) - { - $out = ""; - // Now, loop again, finding questions (rows) - foreach( $this->leftList as $leftElt ) - { - $responseIdent = $questionIdent . "_A_" . $leftElt['code']; - $out.= '' . "\n" - . '\n" - . ' ' . "\n"; - - foreach( $this->rightList as $rightElt ) - { - $out.= ' ' . "\n" - . " \n" - . " \n"; - } - - $out.= "\n"; - } - - return $out; - } - - /** - * Export the response processing part - * @author Amand Tihon - */ - function imsExportProcessing($questionIdent) - { - $out = ""; - foreach( $this->leftList as $leftElt ) - { - $responseIdent = $questionIdent . "_A_" . $leftElt['code']; - $out.= ' ' . "\n" - . ' ' . $leftElt['match'] . "\n" - . ' ' . $leftElt['grade'] . "\n" - . " \n"; - } - return $out; - } - - /** - * Export the feedback (comments to selected answers) to IMS/QTI - * - * @author Amand Tihon - */ - function imsExportFeedback($questionIdent) - { - // no feedback in this question type - return ''; - } - - /** - * allow to import the answers, feedbacks, and grades of a question - * - * @param questionArray is an array that must contain all the information needed to build the question - * @author Guillaume Lederer - */ - - function import($questionArray) - { - $answerArray = $questionArray['answer']; - - //This tick to remove examples in the answers!!!! - $this->leftList = array(); - $this->rightList = array(); - - //find right and left column - - $right_column = array_pop($answerArray); - $left_column = array_pop($answerArray); - - //1- build answers - - foreach ($right_column as $right_key => $right_element) - { - $code = $this->addRight($right_element); - - foreach ($left_column as $left_key => $left_element) - { - $matched_pattern = $left_key." ".$right_key; - $matched_pattern_inverted = $right_key." ".$left_key; - - - if (in_array($matched_pattern, $questionArray['correct_answers']) || in_array($matched_pattern_inverted, $questionArray['correct_answers'])) - { - if (isset($questionArray['weighting'][$matched_pattern])) - { - $grade = $questionArray['weighting'][$matched_pattern]; - } - else - { - $grade = 0; - } - $this->addLeft($left_element, $code, $grade); - } - } - } - } -} -?> diff --git a/main/exercice/export/qti/qti_export.php b/main/exercice/export/qti/qti_export.php deleted file mode 100755 index 8a89be0d2b..0000000000 --- a/main/exercice/export/qti/qti_export.php +++ /dev/null @@ -1,351 +0,0 @@ - - * @author Amand Tihon - * @author Sebastien Piraux - * @author Yannick Warnier - * @package chamilo.exercise.qti - */ -/** - * Code - */ -if ( count( get_included_files() ) == 1 ) die( '---' ); -include dirname(__FILE__) . '/qti_classes.php'; -/*-------------------------------------------------------- - Classes - --------------------------------------------------------*/ - -/** - * This class represents an entire exercise to be exported in IMS/QTI. - * It will be represented by a single
containing several . - * - * Some properties cannot be exported, as IMS does not support them : - * - type (one page or multiple pages) - * - start_date and end_date - * - max_attempts - * - show_answer - * - anonymous_attempts - * - * @author Amand Tihon - * @package chamilo.exercise.qti - */ -class ImsSection -{ - var $exercise; - - /** - * Constructor. - * @param $exe The Exercise instance to export - * @author Amand Tihon - */ - function ImsSection($exe) - { - $this->exercise = $exe; - } - - function start_section() - { - $out = '
' . "\n"; - return $out; - } - - function end_section() - { - return "
\n"; - } - - function export_duration() - { - if ($max_time = $this->exercise->getTimeLimit()) - { - // return exercise duration in ISO8601 format. - $minutes = floor($max_time / 60); - $seconds = $max_time % 60; - return 'PT' . $minutes . 'M' . $seconds . "S\n"; - } - else - { - return ''; - } - } - - /** - * Export the presentation (Exercise's description) - * @author Amand Tihon - */ - function export_presentation() - { - $out = "\n" - . " exercise->getDescription() . "]]>\n" - . "\n"; - return $out; - } - - /** - * Export the ordering information. - * Either sequential, through all questions, or random, with a selected number of questions. - * @author Amand Tihon - */ - function export_ordering() - { - $out = ''; - if ($n = $this->exercise->getShuffle()) { - $out.= "" - . " \n" - . " " . $n . "\n" - . " \n" - . ' ' - . "\n\n"; - } - else - { - $out.= '' . "\n" - . " \n" - . "\n"; - } - - return $out; - } - - /** - * Export the questions, as a succession of - * @author Amand Tihon - */ - function export_questions() - { - $out = ""; - foreach ($this->exercise->getQuestionList() as $q) - { - $out .= export_question($q['id'], False); - } - return $out; - } - - /** - * Export the exercise in IMS/QTI. - * - * @param bool $standalone Wether it should include XML tag and DTD line. - * @return a string containing the XML flow - * @author Amand Tihon - */ - function export($standalone) - { - global $charset; - - $head = $foot = ""; - if ($standalone) { - $head = '' . "\n" - . '' . "\n" - . "\n"; - $foot = "\n"; - } - - $out = $head - . $this->start_section() - . $this->export_duration() - . $this->export_presentation() - . $this->export_ordering() - . $this->export_questions() - . $this->end_section() - . $foot; - - return $out; - } -} - -/* - Some quick notes on identifiers generation. - The IMS format requires some blocks, like items, responses, feedbacks, to be uniquely - identified. - The unicity is mandatory in a single XML, of course, but it's prefered that the identifier stays - coherent for an entire site. - - Here's the method used to generate those identifiers. - Question identifier :: "QST_" + + "_" + - Response identifier :: + "_A_" + - Condition identifier :: + "_C_" + - Feedback identifier :: + "_F_" + -*/ -/** - * An IMS/QTI item. It corresponds to a single question. - * This class allows export from Claroline to IMS/QTI XML format. - * It is not usable as-is, but must be subclassed, to support different kinds of questions. - * - * Every start_*() and corresponding end_*(), as well as export_*() methods return a string. - * - * Warning: Attached files are NOT exported. - * @package chamilo.exercise.qti - * @author Amand Tihon - */ -class ImsItem -{ - var $question; - var $question_ident; - var $answer; - - /** - * Constructor. - * - * @param $question The Question object we want to export. - * @author Anamd Tihon - */ - function ImsItem($question) - { - $this->question = $question; - $this->answer = $question->answer; - $this->questionIdent = "QST_" . $question->getId() ; - } - - /** - * Start the XML flow. - * - * This opens the block, with correct attributes. - * - * @author Amand Tihon - */ - function start_item() - { - return '' . "\n"; - } - - /** - * End the XML flow, closing the tag. - * - * @author Amand Tihon - */ - function end_item() - { - return "\n"; - } - - /** - * Create the opening, with the question itself. - * - * This means it opens the but doesn't close it, as this is the role of end_presentation(). - * Inbetween, the export_responses from the subclass should have been called. - * - * @author Amand Tihon - */ - function start_presentation() - { - return '' . "\n" - . 'question->getDescription() . "]]>\n"; - } - - /** - * End the part, opened by export_header. - * - * @author Amand Tihon - */ - function end_presentation() - { - return "\n"; - } - - /** - * Start the response processing, and declare the default variable, SCORE, at 0 in the outcomes. - * - * @author Amand Tihon - */ - function start_processing() - { - return '' . "\n"; - } - - /** - * End the response processing part. - * - * @author Amand Tihon - */ - function end_processing() - { - return "\n"; - } - - - /** - * Export the question as an IMS/QTI Item. - * - * This is a default behaviour, some classes may want to override this. - * - * @param $standalone: Boolean stating if it should be exported as a stand-alone question - * @return A string, the XML flow for an Item. - * @author Amand Tihon - */ - function export($standalone = False) - { - global $charset; - $head = $foot = ""; - - if( $standalone ) - { - $head = '' . "\n" - . '' . "\n" - . "\n"; - $foot = "\n"; - } - - return $head - . $this->start_item() - . $this->start_presentation() - . $this->answer->imsExportResponses($this->questionIdent) - . $this->end_presentation() - . $this->start_processing() - . $this->answer->imsExportProcessing($this->questionIdent) - . $this->end_processing() - . $this->answer->imsExportFeedback($this->questionIdent) - . $this->end_item() - . $foot; - } -} - - - - -/*-------------------------------------------------------- - Functions - --------------------------------------------------------*/ - -/** - * Send a complete exercise in IMS/QTI format, from its ID - * - * @param int $exerciseId The exercise to exporte - * @param boolean $standalone Wether it should include XML tag and DTD line. - * @return The XML as a string, or an empty string if there's no exercise with given ID. - * @author Amand Tihon - */ -function export_exercise($exerciseId, $standalone=True) -{ - $exercise = new Exercise(); - if (! $exercise->load($exerciseId)) - { - return ''; - } - $ims = new ImsSection($exercise); - $xml = $ims->export($standalone); - return $xml; -} - -/** - * Returns the XML flow corresponding to one question - * - * @param int The question ID - * @param bool standalone (ie including XML tag, DTD declaration, etc) - * @author Amand Tihon - */ -function export_question($questionId, $standalone=True) -{ - $question = new ImsQuestion(); - if( !$question->load($questionId) ) - { - return ''; - } - - $ims = new ImsItem($question); - - return $ims->export($standalone); - -} - -?> diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index c0daa423eb..a59094c5aa 100755 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -841,9 +841,8 @@ return array( 'ImsAnswerMultipleChoice' => $baseDir . '/main/exercice/export/qti/qti_classes.php', 'ImsAnswerTrueFalse' => $baseDir . '/main/exercice/export/qti/qti_classes.php', 'ImsAssessmentItem' => $baseDir . '/main/exercice/export/qti2/qti2_export.php', - 'ImsItem' => $baseDir . '/main/exercice/export/qti/qti_export.php', - 'ImsQuestion' => $baseDir . '/main/exercice/export/qti/qti_classes.php', - 'ImsSection' => $baseDir . '/main/exercice/export/qti/qti_export.php', + 'ImsItem' => $baseDir . '/main/exercice/export/qti2/qti2_export.php', + 'ImsSection' => $baseDir . '/main/exercice/export/qti2/qti2_export.php', 'IndexManager' => $baseDir . '/main/inc/lib/userportal.lib.php', 'IndexableChunk' => $baseDir . '/main/inc/lib/search/IndexableChunk.class.php', 'Inline_Frame_Decorator' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/inline_frame_decorator.cls.php',