diff --git a/composer.json b/composer.json
index 7afb96bf1d2..24a2aac9bbc 100755
--- a/composer.json
+++ b/composer.json
@@ -42,6 +42,8 @@
"ext-xml": "*",
"ext-json": "*",
"ext-mbstring": "*",
+ "ext-libxml": "*",
+ "ext-dom": "*",
"twig/twig": "1.*",
"twig/extensions": "~1.0",
"doctrine/orm": "~2.4",
@@ -109,7 +111,8 @@
"culqi/culqi-php": "1.3.4",
"knplabs/knp-components": "~1.3",
"guzzlehttp/guzzle": "~6.0",
- "onelogin/php-saml": "^3.0"
+ "onelogin/php-saml": "^3.0",
+ "symfony/dom-crawler": "~3.4"
},
"require-dev": {
"behat/behat": "@stable",
diff --git a/main/admin/skills_import.php b/main/admin/skills_import.php
index fc6baeded26..2b338cad4de 100755
--- a/main/admin/skills_import.php
+++ b/main/admin/skills_import.php
@@ -98,76 +98,6 @@ function parse_csv_data($file)
return $skills;
}
-/**
- * XML-parser: handle start of element.
- */
-function element_start($parser, $data)
-{
- $data = api_utf8_decode($data);
- global $skill;
- global $current_tag;
- switch ($data) {
- case 'Skill':
- $skill = [];
- break;
- default:
- $current_tag = $data;
- }
-}
-
-/**
- * XML-parser: handle end of element.
- */
-function element_end($parser, $data)
-{
- $data = api_utf8_decode($data);
- global $skill;
- global $skills;
- global $current_value;
- switch ($data) {
- case 'Skill':
- $skills[] = $skill;
- break;
- default:
- $skill[$data] = $current_value;
- break;
- }
-}
-
-/**
- * XML-parser: handle character data.
- */
-function character_data($parser, $data)
-{
- $data = trim(api_utf8_decode($data));
- global $current_value;
- $current_value = $data;
-}
-
-/**
- * Read the XML-file.
- *
- * @param string $file Path to the XML-file
- *
- * @return array All userinformation read from the file
- */
-function parse_xml_data($file)
-{
- global $current_tag;
- global $current_value;
- global $skill;
- global $skills;
- $skills = [];
- $parser = xml_parser_create('UTF-8');
- xml_set_element_handler($parser, 'element_start', 'element_end');
- xml_set_character_data_handler($parser, 'character_data');
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
- xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
- xml_parser_free($parser);
-
- return $skills;
-}
-
$this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script(true);
@@ -183,7 +113,7 @@ function parse_xml_data($file)
$file_type = $_POST['file_type'];
Security::clear_token();
$tok = Security::get_token();
- $allowed_file_mimetype = ['csv', 'xml'];
+ $allowed_file_mimetype = ['csv'];
$error_kind_file = false;
$error_message = '';
@@ -194,10 +124,6 @@ function parse_xml_data($file)
$skills = parse_csv_data($_FILES['import_file']['tmp_name']);
$errors = validate_data($skills);
$error_kind_file = false;
- } elseif (strcmp($file_type, 'xml') === 0 && $ext_import_file == $allowed_file_mimetype[1]) {
- $skills = parse_xml_data($_FILES['import_file']['tmp_name']);
- $errors = validate_data($skills);
- $error_kind_file = false;
} else {
$error_kind_file = true;
}
@@ -222,8 +148,6 @@ function parse_xml_data($file)
if (strcmp($file_type, 'csv') === 0) {
save_data($skills_to_insert);
- } elseif (strcmp($file_type, 'xml') === 0) {
- save_data($skills_to_insert);
} else {
$error_message = get_lang('YouMustImportAFileAccordingToSelectedOption');
}
@@ -272,7 +196,7 @@ function parse_xml_data($file)
'radio',
'file_type',
'',
- 'CSV ('.get_lang('ExampleCSVFile').')',
+ 'CSV ('.get_lang('ExampleCSVFile').')',
'csv'
);
$form->addGroup($group, '', get_lang('FileType'));
@@ -283,23 +207,6 @@ function parse_xml_data($file)
$form->setDefaults($defaults);
$form->display();
-$list = [];
-$list_reponse = [];
-$result_xml = '';
-$i = 0;
-$count_fields = count($extra_fields);
-if ($count_fields > 0) {
- foreach ($extra_fields as $extra) {
- $list[] = $extra[1];
- $list_reponse[] = 'xxx';
- $spaces = ' ';
- $result_xml .= $spaces.'<'.$extra[1].'>xxx</'.$extra[1].'>';
- if ($i != $count_fields - 1) {
- $result_xml .= '
';
- }
- $i++;
- }
-}
?>
:
diff --git a/main/admin/user_import.php b/main/admin/user_import.php
index d564519b938..bce7dd5c187 100644
--- a/main/admin/user_import.php
+++ b/main/admin/user_import.php
@@ -307,66 +307,6 @@ function parse_csv_data($file)
return $users;
}
-/**
- * XML-parser: handle start of element.
- *
- * @param string $parser Deprecated?
- * @param string $data The data to be parsed
- */
-function element_start($parser, $data)
-{
- $data = api_utf8_decode($data);
- global $user;
- global $current_tag;
- switch ($data) {
- case 'Contact':
- $user = [];
- break;
- default:
- $current_tag = $data;
- }
-}
-
-/**
- * XML-parser: handle end of element.
- *
- * @param string $parser Deprecated?
- * @param string $data The data to be parsed
- */
-function element_end($parser, $data)
-{
- $data = api_utf8_decode($data);
- global $user;
- global $users;
- global $current_value;
- switch ($data) {
- case 'Contact':
- if ($user['Status'] == '5') {
- $user['Status'] = STUDENT;
- }
- if ($user['Status'] == '1') {
- $user['Status'] = COURSEMANAGER;
- }
- $users[] = $user;
- break;
- default:
- $user[$data] = $current_value;
- break;
- }
-}
-
-/**
- * XML-parser: handle character data.
- *
- * @param string $parser Parser (deprecated?)
- * @param string $data The data to be parsed
- */
-function character_data($parser, $data)
-{
- $data = trim(api_utf8_decode($data));
- global $current_value;
- $current_value = $data;
-}
/**
* Read the XML-file.
@@ -377,16 +317,23 @@ function character_data($parser, $data)
*/
function parse_xml_data($file)
{
- global $users;
- $users = [];
- $parser = xml_parser_create('UTF-8');
- xml_set_element_handler($parser, 'element_start', 'element_end');
- xml_set_character_data_handler($parser, 'character_data');
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
- xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
- xml_parser_free($parser);
+ $crawler = new \Symfony\Component\DomCrawler\Crawler();
+ $crawler->addXmlContent(file_get_contents($file));
+ $crawler = $crawler->filter('Contacts > Contact ');
+ $array = [];
+ foreach ($crawler as $domElement) {
+ $row = [];
+ foreach ($domElement->childNodes as $node) {
+ if ($node->nodeName != '#text') {
+ $row[$node->nodeName] = $node->nodeValue;
+ }
+ }
+ if (!empty($row)) {
+ $array[] = $row;
+ }
+ }
- return $users;
+ return $array;
}
$this_section = SECTION_PLATFORM_ADMIN;
@@ -520,14 +467,14 @@ function parse_xml_data($file)
'radio',
'file_type',
'',
- 'CSV ('.get_lang('ExampleCSVFile').')',
+ 'CSV ('.get_lang('ExampleCSVFile').')',
'csv'
),
$form->createElement(
'radio',
'file_type',
null,
- 'XML ('.get_lang('ExampleXMLFile').')',
+ 'XML ('.get_lang('ExampleXMLFile').')',
'xml'
),
];
diff --git a/main/admin/user_update_import.php b/main/admin/user_update_import.php
index bb302f6d1ac..afedaac9432 100644
--- a/main/admin/user_update_import.php
+++ b/main/admin/user_update_import.php
@@ -254,86 +254,26 @@ function parse_csv_data($file)
return $users;
}
-/**
- * XML-parser: handle start of element.
- *
- * @param string $parser Deprecated?
- * @param string $data The data to be parsed
- */
-function element_start($parser, $data)
-{
- $data = api_utf8_decode($data);
- global $user;
- global $current_tag;
- switch ($data) {
- case 'Contact':
- $user = [];
- break;
- default:
- $current_tag = $data;
- }
-}
-/**
- * XML-parser: handle end of element.
- *
- * @param string $parser Deprecated?
- * @param string $data The data to be parsed
- */
-function element_end($parser, $data)
+function parse_xml_data($file)
{
- $data = api_utf8_decode($data);
- global $user;
- global $users;
- global $current_value;
- switch ($data) {
- case 'Contact':
- if ($user['Status'] == '5') {
- $user['Status'] = STUDENT;
- }
- if ($user['Status'] == '1') {
- $user['Status'] = COURSEMANAGER;
+ $crawler = new \Symfony\Component\DomCrawler\Crawler();
+ $crawler->addXmlContent(file_get_contents($file));
+ $crawler = $crawler->filter('Contacts > Contact ');
+ $array = [];
+ foreach ($crawler as $domElement) {
+ $row = [];
+ foreach ($domElement->childNodes as $node) {
+ if ($node->nodeName != '#text') {
+ $row[$node->nodeName] = $node->nodeValue;
}
- $users[] = $user;
- break;
- default:
- $user[$data] = $current_value;
- break;
+ }
+ if (!empty($row)) {
+ $array[] = $row;
+ }
}
-}
-/**
- * XML-parser: handle character data.
- *
- * @param string $parser Parser (deprecated?)
- * @param string $data The data to be parsed
- */
-function character_data($parser, $data)
-{
- $data = trim(api_utf8_decode($data));
- global $current_value;
- $current_value = $data;
-}
-
-/**
- * Read the XML-file.
- *
- * @param string $file Path to the XML-file
- *
- * @return array All user information read from the file
- */
-function parse_xml_data($file)
-{
- global $users;
- $users = [];
- $parser = xml_parser_create('UTF-8');
- xml_set_element_handler($parser, 'element_start', 'element_end');
- xml_set_character_data_handler($parser, 'character_data');
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
- xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
- xml_parser_free($parser);
-
- return $users;
+ return $array;
}
$this_section = SECTION_PLATFORM_ADMIN;
@@ -429,7 +369,7 @@ function parse_xml_data($file)
exit;
}
}
-Display :: display_header($tool_name);
+Display::display_header($tool_name);
if (!empty($error_message)) {
echo Display::return_message($error_message, 'error');
diff --git a/main/admin/usergroup_import.php b/main/admin/usergroup_import.php
index 1b3fef693e3..b33e35873a9 100755
--- a/main/admin/usergroup_import.php
+++ b/main/admin/usergroup_import.php
@@ -100,7 +100,7 @@ function save_data($classes)
'radio',
'file_type',
'',
- 'CSV ('.get_lang('ExampleCSVFile').')',
+ 'CSV ('.get_lang('ExampleCSVFile').')',
'csv'
);
$form->addGroup($group, '', get_lang('FileType'), null);
diff --git a/main/exercise/export/exercise_import.inc.php b/main/exercise/export/exercise_import.inc.php
index 9f4a16dd226..7180e09275e 100755
--- a/main/exercise/export/exercise_import.inc.php
+++ b/main/exercise/export/exercise_import.inc.php
@@ -2,6 +2,7 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
+use Symfony\Component\DomCrawler\Crawler;
/**
* @copyright (c) 2001-2006 Universite catholique de Louvain (UCL)
@@ -65,12 +66,7 @@ function get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath)
*/
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;
+ global $exerciseInfo;
global $resourcesLinks;
$baseWorkDir = api_get_path(SYS_ARCHIVE_PATH).'qti2/';
@@ -85,12 +81,9 @@ function import_exercise($file)
}
// set some default values for the new exercise
- $exercise_info = [];
- $exercise_info['name'] = preg_replace('/.zip$/i', '', $file);
- $exercise_info['question'] = [];
- $element_pile = [];
- // create parser and array to retrieve info from manifest
- $element_pile = []; //pile to known the depth in which we are
+ $exerciseInfo = [];
+ $exerciseInfo['name'] = preg_replace('/.zip$/i', '', $file);
+ $exerciseInfo['question'] = [];
// if file is not a .zip, then we cancel all
if (!preg_match('/.zip$/i', $file)) {
@@ -106,7 +99,7 @@ function import_exercise($file)
// find the different manifests for each question and parse them.
$exerciseHandle = opendir($baseWorkDir);
- $file_found = false;
+ $fileFound = false;
$result = false;
$filePath = null;
$resourcesLinks = [];
@@ -125,7 +118,7 @@ function import_exercise($file)
if ($isQti) {
$result = qti_parse_file($baseWorkDir, $file, $questionFile);
$filePath = $baseWorkDir.$file;
- $file_found = true;
+ $fileFound = true;
} else {
$isManifest = isQtiManifest($baseWorkDir.'/'.$file.'/'.$questionFile);
if ($isManifest) {
@@ -139,7 +132,7 @@ function import_exercise($file)
if ($isQti) {
$result = qti_parse_file($baseWorkDir, '', $file);
$filePath = $baseWorkDir.'/'.$file;
- $file_found = true;
+ $fileFound = true;
} else {
$isManifest = isQtiManifest($baseWorkDir.'/'.$file);
if ($isManifest) {
@@ -149,7 +142,7 @@ function import_exercise($file)
}
}
- if (!$file_found) {
+ if (!$fileFound) {
return 'NoXMLFileFoundInTheZip';
}
@@ -157,23 +150,20 @@ function import_exercise($file)
return false;
}
- $doc = new DOMDocument();
- $doc->load($filePath);
-
// 1. Create exercise.
$exercise = new Exercise();
- $exercise->exercise = $exercise_info['name'];
+ $exercise->exercise = $exerciseInfo['name'];
// Random QTI support
- if (isset($exercise_info['order_type'])) {
- if ($exercise_info['order_type'] == 'Random') {
+ if (isset($exerciseInfo['order_type'])) {
+ if ($exerciseInfo['order_type'] == 'Random') {
$exercise->setQuestionSelectionType(2);
$exercise->random = -1;
}
}
- if (!empty($exercise_info['description'])) {
- $exercise->updateDescription(formatText(strip_tags($exercise_info['description'])));
+ if (!empty($exerciseInfo['description'])) {
+ $exercise->updateDescription(formatText(strip_tags($exerciseInfo['description'])));
}
$exercise->save();
@@ -181,7 +171,7 @@ function import_exercise($file)
$courseId = api_get_course_int_id();
if (!empty($last_exercise_id)) {
// For each question found...
- foreach ($exercise_info['question'] as $question_array) {
+ foreach ($exerciseInfo['question'] as $question_array) {
//2. Create question
$question = new Ims2Question();
$question->type = $question_array['type'];
@@ -300,7 +290,6 @@ function formatText($text)
*/
function qti_parse_file($exercisePath, $file, $questionFile)
{
- global $non_HTML_tag_to_avoid;
global $record_item_body;
global $questionTempDir;
@@ -311,10 +300,13 @@ function qti_parse_file($exercisePath, $file, $questionFile)
Display::addFlash(Display::return_message(get_lang('Error opening question\'s XML file'), 'error'));
return false;
- } else {
- $data = fread($fp, filesize($questionFilePath));
}
+ $data = fread($fp, filesize($questionFilePath));
+
+ //close file
+ fclose($fp);
+
//parse XML question file
//$data = str_replace(array('', '
', '', ''), '', $data);
$data = ChamiloApi::stripGivenTags($data, ['p', 'front']);
@@ -327,53 +319,11 @@ function qti_parse_file($exercisePath, $file, $questionFile)
//used global variable start values declaration:
$record_item_body = false;
- $non_HTML_tag_to_avoid = [
- "SIMPLECHOICE",
- "CHOICEINTERACTION",
- "INLINECHOICEINTERACTION",
- "INLINECHOICE",
- "SIMPLEMATCHSET",
- "SIMPLEASSOCIABLECHOICE",
- "TEXTENTRYINTERACTION",
- "FEEDBACKINLINE",
- "MATCHINTERACTION",
- 'EXTENDEDTEXTINTERACTION',
- "ITEMBODY",
- "BR",
- "IMG",
- ];
-
- $question_format_supported = true;
- $xml_parser = xml_parser_create();
- xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, false);
- if ($qtiMainVersion == 1) {
- xml_set_element_handler(
- $xml_parser,
- 'startElementQti1',
- 'endElementQti1'
- );
- xml_set_character_data_handler($xml_parser, 'elementDataQti1');
- } else {
- xml_set_element_handler(
- $xml_parser,
- 'startElementQti2',
- 'endElementQti2'
- );
- xml_set_character_data_handler($xml_parser, 'elementDataQti2');
- }
-
- 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
+ if ($qtiMainVersion != 2) {
Display::addFlash(
Display::return_message(
- get_lang('Error reading XML file').
- sprintf(
- '[%d:%d]',
- xml_get_current_line_number($xml_parser),
- xml_get_current_column_number($xml_parser)
- ),
+ get_lang('UnsupportedQtiVersion'),
'error'
)
);
@@ -381,682 +331,293 @@ function qti_parse_file($exercisePath, $file, $questionFile)
return false;
}
- //close file
- fclose($fp);
- if (!$question_format_supported) {
- Display::addFlash(
- Display::return_message(
- get_lang(
- 'Unknown question format in file %file',
- [
- '%file' => $questionFile,
- ]
- ),
- 'error'
- )
- );
-
- return false;
- }
+ parseQti2($data);
return true;
}
/**
- * Function used by the SAX xml parser when the parser meets a opening tag.
+ * Function used to parser a QTI2 xml file
*
- * @param object $parser xml parser created with "xml_parser_create()"
- * @param string $name name of the element
- * @param array $attributes
+ * @param string $xmlData
*/
-function startElementQti2($parser, $name, $attributes)
+function parseQti2($xmlData)
{
- 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 $exerciseInfo;
global $questionTempDir;
+ global $resourcesLinks;
- 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) {
- $grand_parent_element = $element_pile[sizeof($element_pile) - 3];
- } else {
- $grand_parent_element = '';
- }
- if (sizeof($element_pile) >= 4) {
- $great_grand_parent_element = $element_pile[sizeof($element_pile) - 4];
- } else {
- $great_grand_parent_element = '';
- }
+ $crawler = new Crawler($xmlData);
+ $nodes = $crawler->filter('*');
+
+ $currentQuestionIdent = '';
+ $currentAnswerId = '';
+ $currentQuestionItemBody = '';
+ $cardinality = '';
+ $nonHTMLTagToAvoid = [
+ "simpleChoice",
+ "choiceInteraction",
+ "inlineChoiceInteraction",
+ "inlineChoice",
+ "soMPLEMATCHSET",
+ "simpleAssociableChoice",
+ "textEntryInteraction",
+ "feedbackInline",
+ "matchInteraction",
+ 'extendedTextInteraction',
+ "itemBody",
+ "br",
+ "img",
+ ];
+ $currentMatchSet = null;
- 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 .= "
";
- }
+ /** @var DOMElement $node */
+ foreach ($nodes as $node) {
+ if ('#text' === $node->nodeName) {
+ continue;
}
- }
- switch ($current_element) {
- case 'ASSESSMENTITEM':
- // retrieve current question
- $current_question_ident = $attributes['IDENTIFIER'];
- $exercise_info['question'][$current_question_ident] = [];
- $exercise_info['question'][$current_question_ident]['answer'] = [];
- $exercise_info['question'][$current_question_ident]['correct_answers'] = [];
- $exercise_info['question'][$current_question_ident]['title'] = isset($attributes['TITLE']) ? $attributes['TITLE'] : '';
- $exercise_info['question'][$current_question_ident]['category'] = isset($attributes['CATEGORY']) ? $attributes['CATEGORY'] : '';
- $exercise_info['question'][$current_question_ident]['tempdir'] = $questionTempDir;
- break;
- case 'SECTION':
- //retrieve exercise name
- if (isset($attributes['TITLE']) && !empty($attributes['TITLE'])) {
- $exercise_info['name'] = $attributes['TITLE'];
- }
- break;
- case 'RESPONSEDECLARATION':
- // Retrieve question type
- if ('multiple' == $attributes['CARDINALITY']) {
- $exercise_info['question'][$current_question_ident]['type'] = MCMA;
- $cardinality = 'multiple';
- }
- if ('single' == $attributes['CARDINALITY']) {
- $exercise_info['question'][$current_question_ident]['type'] = MCUA;
- $cardinality = 'single';
- }
- //needed for FIB
- $current_answer_id = $attributes['IDENTIFIER'];
- 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':
- $current_inlinechoice_id = $attributes['IDENTIFIER'];
- 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 'EXTENDEDTEXTINTERACTION':
- $exercise_info['question'][$current_question_ident]['type'] = FREE_ANSWER;
- $exercise_info['question'][$current_question_ident]['description'] = '';
- 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] = [];
- break;
- case 'SIMPLEASSOCIABLECHOICE':
- $currentAssociableChoice = $attributes['IDENTIFIER'];
- 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] = [];
- }
- break;
- case 'MAPENTRY':
- if ($parent_element == 'MAPPING' || $parent_element == 'MAPENTRY') {
- $answer_id = $attributes['MAPKEY'];
- if (!isset($exercise_info['question'][$current_question_ident]['weighting'])) {
- $exercise_info['question'][$current_question_ident]['weighting'] = [];
+ switch ($node->nodeName) {
+ case 'assessmentItem':
+ $currentQuestionIdent = $node->getAttribute('identifier');
+
+ $exerciseInfo['question'][$currentQuestionIdent] = [
+ 'answer' => [],
+ 'correct_answers' => [],
+ 'title' => $node->getAttribute('title'),
+ 'category' => $node->getAttribute('category'),
+ 'type' => '',
+ 'tempdir' => $questionTempDir,
+ ];
+ break;
+ case 'section':
+ $title = $node->getAttribute('title');
+
+ if (!empty($title)) {
+ $exerciseInfo['name'] = $title;
+ }
+ break;
+ case 'responseDeclaration':
+ if ('multiple' === $node->getAttribute('cardinality')) {
+ $exerciseInfo['question'][$currentQuestionIdent]['type'] = MCMA;
+ $cardinality = 'multiple';
}
- $exercise_info['question'][$current_question_ident]['weighting'][$answer_id] = $attributes['MAPPEDVALUE'];
- }
- break;
- case 'MAPPING':
- if (isset($attributes['DEFAULTVALUE'])) {
- $exercise_info['question'][$current_question_ident]['default_weighting'] = $attributes['DEFAULTVALUE'];
- }
- // no break ?
- case 'ITEMBODY':
- $record_item_body = true;
- $current_question_item_body = '';
- break;
- case 'IMG':
- $exercise_info['question'][$current_question_ident]['attached_file_url'] = $attributes['SRC'];
- break;
- case 'ORDER':
- if (isset($attributes['ORDER_TYPE'])) {
- $exercise_info['order_type'] = $attributes['ORDER_TYPE'];
- }
- break;
- }
-}
-
-/**
- * Function used by the SAX xml parser when the parser meets a closing tag.
- *
- * @param $parser xml parser created with "xml_parser_create()"
- * @param $name name of the element
- */
-function endElementQti2($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;
-
- 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) {
- $grand_parent_element = $element_pile[sizeof($element_pile) - 3];
- } else {
- $grand_parent_element = '';
- }
- if (sizeof($element_pile) >= 4) {
- $great_grand_parent_element = $element_pile[sizeof($element_pile) - 4];
- } else {
- $great_grand_parent_element = '';
- }
- //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 .= "".$name.">";
- }
+ if ('single' === $node->getAttribute('cardinality')) {
+ $exerciseInfo['question'][$currentQuestionIdent]['type'] = MCUA;
+ $cardinality = 'single';
+ }
- 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 {
- if ($exercise_info['question'][$current_question_ident]['type'] == FREE_ANSWER) {
- $current_question_item_body = trim($current_question_item_body);
- if (!empty($current_question_item_body)) {
- $exercise_info['question'][$current_question_ident]['description'] = $current_question_item_body;
+ $currentAnswerId = $node->getAttribute('identifier');
+ break;
+ case 'inlineChoiceInteraction':
+ $exerciseInfo['question'][$currentQuestionIdent]['type'] = FIB;
+ $exerciseInfo['question'][$currentQuestionIdent]['subtype'] = 'LISTBOX_FILL';
+ $currentAnswerId = $node->getAttribute('responseIdentifier');
+ break;
+ case 'inlineChoice':
+ $answerIdentifier = $exerciseInfo['question'][$currentQuestionIdent]['correct_answers'][$currentAnswerId];
+
+ if ($node->getAttribute('identifier') == $answerIdentifier) {
+ $currentQuestionItemBody = str_replace(
+ "**claroline_start**".$currentAnswerId."**claroline_end**",
+ "[".$node->nodeValue."]",
+ $currentQuestionItemBody
+ );
+ } else {
+ if (!isset($exerciseInfo['question'][$currentQuestionIdent]['wrong_answers'])) {
+ $exerciseInfo['question'][$currentQuestionIdent]['wrong_answers'] = [];
}
+
+ $exerciseInfo['question'][$currentQuestionIdent]['wrong_answers'][] = $node->nodeValue;
+ }
+ break;
+ case 'textEntryInteraction':
+ $exerciseInfo['question'][$currentQuestionIdent]['type'] = FIB;
+ $exerciseInfo['question'][$currentQuestionIdent]['subtype'] = 'TEXTFIELD_FILL';
+ $exerciseInfo['question'][$currentQuestionIdent]['response_text'] = $currentQuestionItemBody;
+ break;
+ case 'matchInteraction':
+ $exerciseInfo['question'][$currentQuestionIdent]['type'] = MATCHING;
+ break;
+ case 'extendedTextInteraction':
+ $exerciseInfo['question'][$currentQuestionIdent]['type'] = FREE_ANSWER;
+ $exerciseInfo['question'][$currentQuestionIdent]['description'] = $node->nodeValue;
+ break;
+ case 'simpleMatchSet':
+ if (!isset($currentMatchSet)) {
+ $currentMatchSet = 1;
} else {
- $exercise_info['question'][$current_question_ident]['statement'] = $current_question_item_body;
+ $currentMatchSet++;
+ }
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentMatchSet] = [];
+ break;
+ case 'simpleAssociableChoice':
+ $currentAssociableChoice = $node->getAttribute('identifier');
+
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentMatchSet][$currentAssociableChoice] = trim($node->nodeValue);
+ break;
+ case 'simpleChoice':
+ $currentAnswerId = $node->getAttribute('identifier');
+ if (!isset($exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId])) {
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId] = [];
}
- }
- break;
- }
- array_pop($element_pile);
-}
-
-/**
- * @param $parser
- * @param $data
- */
-function elementDataQti2($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;
- global $resourcesLinks;
-
- $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) {
- $grand_parent_element = $element_pile[sizeof($element_pile) - 3];
- } else {
- $grand_parent_element = '';
- }
- if (sizeof($element_pile) >= 4) {
- $great_grand_parent_element = $element_pile[sizeof($element_pile) - 4];
- } else {
- $great_grand_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 'EXTENDEDTEXTINTERACTION':
- $exercise_info['question'][$current_question_ident]['description'] .= $data;
- break;
- 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);
- }
- 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':
- if ($parent_element == 'CORRECTRESPONSE') {
- if ($cardinality == 'single') {
- $exercise_info['question'][$current_question_ident]['correct_answers'][$data] = $data;
+ if (!isset($exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId]['value'])) {
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId]['value'] = trim(
+ $node->nodeValue
+ );
} else {
- $exercise_info['question'][$current_question_ident]['correct_answers'][] = $data;
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId]['value'] .= ''
+ .trim($node->nodeValue);
}
- }
+ break;
+ case 'mapEntry':
+ if (in_array($node->parentNode->nodeName, ['mapping', 'mapEntry'])) {
+ $answer_id = $node->getAttribute('mapKey');
- // Getting score of free answer
- if ($grand_parent_element == 'OUTCOMEDECLARATION') {
- if (!empty(trim($data))) {
- $exercise_info['question'][$current_question_ident]['weighting'][0] = trim($data);
- }
- }
+ if (!isset($exerciseInfo['question'][$currentQuestionIdent]['weighting'])) {
+ $exerciseInfo['question'][$currentQuestionIdent]['weighting'] = [];
+ }
- break;
- case 'ITEMBODY':
- // Replace relative links by links to the documents in the course
- // $resourcesLinks is only defined by qtiProcessManifest()
- if (isset($resourcesLinks) && isset($resourcesLinks['manifest']) && isset($resourcesLinks['web'])) {
- foreach ($resourcesLinks['manifest'] as $key => $value) {
- $data = preg_replace('|'.$value.'|', $resourcesLinks['web'][$key], $data);
- }
- }
- $current_question_item_body .= $data;
- 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
- );
- } else {
- if (!isset($exercise_info['question'][$current_question_ident]['wrong_answers'])) {
- $exercise_info['question'][$current_question_ident]['wrong_answers'] = [];
+ $exerciseInfo['question'][$currentQuestionIdent]['weighting'][$answer_id] = $node->getAttribute(
+ 'mappedValue'
+ );
}
- $exercise_info['question'][$current_question_ident]['wrong_answers'][] = $data;
- }
- break;
- case 'MATTEXT':
- if ($grand_parent_element == 'FLOW_MAT' &&
- ($great_grand_parent_element == 'PRESENTATION_MATERIAL' || $great_grand_parent_element == 'SECTION')
- ) {
- if (!empty(trim($data))) {
- $exercise_info['description'] = $data;
+ break;
+ case 'mapping':
+ $defaultValue = $node->getAttribute('defaultValue');
+
+ if (!empty($defaultValue)) {
+ $exerciseInfo['question'][$currentQuestionIdent]['default_weighting'] = $defaultValue;
}
- }
- break;
- }
-}
+ // no break ?
+ case 'itemBody':
+ $nodeValue = $node->nodeValue;
-/**
- * Function used by the SAX xml parser when the parser meets a opening tag for QTI1.
- *
- * @param object $parser xml parser created with "xml_parser_create()"
- * @param string $name name of the element
- * @param array $attributes
- */
-function startElementQti1($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;
- global $lastLabelFieldName;
- global $lastLabelFieldValue;
-
- 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) {
- $grand_parent_element = $element_pile[sizeof($element_pile) - 3];
- } else {
- $grand_parent_element = "";
- }
- if (sizeof($element_pile) >= 4) {
- $great_grand_parent_element = $element_pile[sizeof($element_pile) - 4];
- } else {
- $great_grand_parent_element = "";
- }
+ $currentQuestionItemBody = '';
- 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 .= "
";
- }
- }
- }
+ /** @var DOMElement $childNode */
+ foreach ($node->childNodes as $childNode) {
+ if ('#text' === $childNode->nodeName) {
+ continue;
+ }
- switch ($current_element) {
- case 'ASSESSMENT':
- // This is the assessment element: we don't care, we just want questions
- if (!empty($attributes['TITLE'])) {
- $exercise_info['name'] = $attributes['TITLE'];
- }
- break;
- case 'ITEM':
- //retrieve current question
- $current_question_ident = $attributes['IDENT'];
- $exercise_info['question'][$current_question_ident] = [];
- $exercise_info['question'][$current_question_ident]['answer'] = [];
- $exercise_info['question'][$current_question_ident]['correct_answers'] = [];
- $exercise_info['question'][$current_question_ident]['tempdir'] = $questionTempDir;
- break;
- case 'SECTION':
- break;
- case 'RESPONSE_LID':
- // Retrieve question type
- if ("multiple" == strtolower($attributes['RCARDINALITY'])) {
- $cardinality = 'multiple';
- }
- if ("single" == strtolower($attributes['RCARDINALITY'])) {
- $cardinality = 'single';
- }
- //needed for FIB
- $current_answer_id = $attributes['IDENT'];
- $current_question_item_body = '';
- break;
- case 'RENDER_CHOICE':
- break;
- case 'RESPONSE_LABEL':
- if (!empty($attributes['IDENT'])) {
- $current_answer_id = $attributes['IDENT'];
- //set the placeholder for the answer to come (in endElementQti1)
- $exercise_info['question'][$current_question_ident]['answer'][$current_answer_id] = '';
- }
- break;
- case 'DECVAR':
- if ($parent_element == 'OUTCOMES' && $grand_parent_element == 'RESPROCESSING') {
- // The following attributes are available
- //$attributes['VARTYPE'];
- //$attributes['DEFAULTVAL'];
- //$attributes['MINVALUE'];
- //$attributes['MAXVALUE'];
- }
- break;
- case 'VAREQUAL':
- if ($parent_element == 'CONDITIONVAR' && $grand_parent_element == 'RESPCONDITION') {
- // The following attributes are available
- //$attributes['RESPIDENT']
- }
- break;
- case 'SETVAR':
- if ($parent_element == 'RESPCONDITION') {
- // The following attributes are available
- //$attributes['ACTION']
- }
- break;
- case 'IMG':
- break;
- case 'MATTEXT':
- if ($parent_element == 'MATERIAL') {
- if ($grand_parent_element == 'PRESENTATION') {
- $exercise_info['question'][$current_question_ident]['title'] = $current_question_item_body;
+ if (!in_array($childNode->nodeName, $nonHTMLTagToAvoid)) {
+ $currentQuestionItemBody .= '<'.$childNode->nodeName;
+
+ if ($childNode->attributes) {
+ foreach ($childNode->attributes as $attribute) {
+ $currentQuestionItemBody .= ' '.$attribute->nodeName.'="'.$attribute->nodeValue.'"';
+ }
+ }
+
+ $currentQuestionItemBody .= '>'
+ .$childNode->nodeValue
+ .''.$node->nodeName.'>';
+
+ continue;
+ }
+
+ if ('inlineChoiceInteraction' === $childNode->nodeName) {
+ $currentQuestionItemBody .= "**claroline_start**"
+ .$childNode->attr('responseIdentifier')
+ ."**claroline_end**";
+
+ continue;
+ }
+
+ if ('textEntryInteraction' === $childNode->nodeName) {
+ $correct_answer_value = $exerciseInfo['question'][$currentQuestionIdent]['correct_answers'][$currentAnswerId];
+ $currentQuestionItemBody .= "[".$correct_answer_value."]";
+
+ continue;
+ }
+
+ if ('br' === $childNode->nodeName) {
+ $currentQuestionItemBody .= '
';
+ }
}
- }
- break;
- }
-}
-/**
- * Function used by the SAX xml parser when the parser meets a closing tag for QTI1.
- *
- * @param object $parser xml parser created with "xml_parser_create()"
- * @param string $name name of the element
- * @param array $attributes The element attributes
- */
-function endElementQti1($parser, $name, $attributes)
-{
- 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;
- global $lastLabelFieldName;
- global $lastLabelFieldValue;
- global $resourcesLinks;
+ // Replace relative links by links to the documents in the course
+ // $resourcesLinks is only defined by qtiProcessManifest()
+ if (isset($resourcesLinks) && isset($resourcesLinks['manifest']) && isset($resourcesLinks['web'])) {
+ foreach ($resourcesLinks['manifest'] as $key => $value) {
+ $nodeValue = preg_replace('|'.$value.'|', $resourcesLinks['web'][$key], $nodeValue);
+ }
+ }
- $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) {
- $grand_parent_element = $element_pile[sizeof($element_pile) - 3];
- } else {
- $grand_parent_element = "";
- }
- if (sizeof($element_pile) >= 4) {
- $great_grand_parent_element = $element_pile[sizeof($element_pile) - 4];
- } else {
- $great_grand_parent_element = "";
- }
+ $currentQuestionItemBody .= $node->firstChild->nodeValue;
- //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 .= "".$name.">";
- }
+ if ($exerciseInfo['question'][$currentQuestionIdent]['type'] == FIB) {
+ $exerciseInfo['question'][$currentQuestionIdent]['response_text'] = $currentQuestionItemBody;
+ } else {
+ if ($exerciseInfo['question'][$currentQuestionIdent]['type'] == FREE_ANSWER) {
+ $currentQuestionItemBody = trim($currentQuestionItemBody);
- switch ($name) {
- case 'MATTEXT':
- if ($parent_element == 'MATERIAL') {
- // For some reason an item in a hierarchy - doesn't seem to
- // catch the grandfather 'presentation', so we check for 'item' as a patch (great-grand-father)
- if ($grand_parent_element == 'PRESENTATION' || $grand_parent_element == 'ITEM') {
- $exercise_info['question'][$current_question_ident]['title'] = $current_question_item_body;
- $current_question_item_body = '';
- } elseif ($grand_parent_element == 'RESPONSE_LABEL') {
- $last = '';
- foreach ($exercise_info['question'][$current_question_ident]['answer'] as $key => $value) {
- $last = $key;
+ if (!empty($currentQuestionItemBody)) {
+ $exerciseInfo['question'][$currentQuestionIdent]['description'] = $currentQuestionItemBody;
+ }
+ } else {
+ $exerciseInfo['question'][$currentQuestionIdent]['statement'] = $currentQuestionItemBody;
}
- $exercise_info['question'][$current_question_ident]['answer'][$last]['value'] = $current_question_item_body;
- $current_question_item_body = '';
}
- }
- // no break ?
- case 'RESPONSE_LID':
- // Retrieve question type
- if (!isset($exercise_info['question'][$current_question_ident]['type'])) {
- if ("multiple" == strtolower($attributes['RCARDINALITY'])) {
- $exercise_info['question'][$current_question_ident]['type'] = MCMA;
+ break;
+ case 'img':
+ $exerciseInfo['question'][$currentQuestionIdent]['attached_file_url'] = $node->getAttribute('src');
+ break;
+ case 'order':
+ $orderType = $node->getAttribute('order_type');
+
+ if (!empty($orderType)) {
+ $exerciseInfo['order_type'] = $orderType;
}
- if ("single" == strtolower($attributes['RCARDINALITY'])) {
- $exercise_info['question'][$current_question_ident]['type'] = MCUA;
+ break;
+ case 'feedbackInline':
+ if (!isset($exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId]['feedback'])) {
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId] = trim(
+ $node->nodeValue
+ );
+ } else {
+ $exerciseInfo['question'][$currentQuestionIdent]['answer'][$currentAnswerId]['feedback'] .= ''
+ .trim(
+ $node->nodeValue
+ );
}
- }
- $current_question_item_body = '';
- //needed for FIB
- $current_answer_id = $attributes['IDENT'];
- break;
- case 'ITEMMETADATA':
- $current_question_item_body = '';
- break;
- }
- array_pop($element_pile);
-}
+ break;
+ case 'value':
+ if ('correctResponse' === $node->parentNode->nodeName) {
+ $nodeValue = trim($node->nodeValue);
-/**
- * QTI1 element parser.
- *
- * @param $parser
- * @param $data
- */
-function elementDataQti1($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;
- global $lastLabelFieldName;
- global $lastLabelFieldValue;
- global $resourcesLinks;
-
- $current_element = end($element_pile);
- if (sizeof($element_pile) >= 2) {
- $parent_element = $element_pile[sizeof($element_pile) - 2];
- } else {
- $parent_element = "";
- }
- //treat the record of the full content of itembody tag (needed for question statment and/or FIB text:
+ if ('single' === $cardinality) {
+ $exerciseInfo['question'][$currentQuestionIdent]['correct_answers'][$nodeValue] = $nodeValue;
+ } else {
+ $exerciseInfo['question'][$currentQuestionIdent]['correct_answers'][] = $nodeValue;
+ }
+ }
- if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) {
- $current_question_item_body .= $data;
- }
+ if ('outcomeDeclaration' === $node->parentNode->parentNode->nodeName) {
+ $nodeValue = trim($node->nodeValue);
- switch ($current_element) {
- case 'FIELDLABEL':
- if (!empty($data)) {
- $lastLabelFieldName = $current_element;
- $lastLabelFieldValue = $data;
- }
- // no break ?
- case 'FIELDENTRY':
- $current_question_item_body = $data;
- switch ($lastLabelFieldValue) {
- case 'cc_profile':
- // The following values might be proprietary in MATRIX software. No specific reference
- // in QTI doc: http://www.imsglobal.org/question/qtiv1p2/imsqti_asi_infov1p2.html#1415855
- switch ($data) {
- case 'cc.true_false.v0p1':
- //this is a true-false question (translated to multiple choice in Chamilo because true-false comes with "I don't know")
- $exercise_info['question'][$current_question_ident]['type'] = MCUA;
- break;
- case 'cc.multiple_choice.v0p1':
- //this is a multiple choice (unique answer) question
- $exercise_info['question'][$current_question_ident]['type'] = MCUA;
- break;
- case 'cc.multiple_response.v0p1':
- //this is a multiple choice (unique answer) question
- $exercise_info['question'][$current_question_ident]['type'] = MCMA;
- break;
+ if (!empty($nodeValue)) {
+ $exerciseInfo['question'][$currentQuestionIdent]['weighting'][0] = $nodeValue;
}
- break;
- case 'cc_weighting':
- //defines the total weight of the question
- $exercise_info['question'][$current_question_ident]['default_weighting'] = $lastLabelFieldValue;
- break;
- case 'assessment_question_identifierref':
- //placeholder - not used yet
- // Possible values are not defined by qti v1.2
- break;
- }
- break;
- case 'MATTEXT':
- // Replace relative links by links to the documents in the course
- // $resourcesLinks is only defined by qtiProcessManifest()
- if (isset($resourcesLinks) && isset($resourcesLinks['manifest']) && isset($resourcesLinks['web'])) {
- foreach ($resourcesLinks['manifest'] as $key => $value) {
- $data = preg_replace('|'.$value.'|', $resourcesLinks['web'][$key], $data);
}
- }
- if (!empty($current_question_item_body)) {
- $current_question_item_body .= $data;
- } else {
- $current_question_item_body = $data;
- }
- break;
- case 'VAREQUAL':
- $lastLabelFieldName = 'VAREQUAL';
- $lastLabelFieldValue = $data;
- break;
- case 'SETVAR':
- if ($parent_element == 'RESPCONDITION') {
- // The following attributes are available
- //$attributes['ACTION']
- $exercise_info['question'][$current_question_ident]['correct_answers'][] = $lastLabelFieldValue;
- $exercise_info['question'][$current_question_ident]['weighting'][$lastLabelFieldValue] = $data;
- }
- break;
+ break;
+ case 'mattext':
+ if ('flow_mat' === $node->parentNode->parentNode->nodeName &&
+ ('presentation_material' === $node->parentNode->parentNode->parentNode->nodeName ||
+ 'section' === $node->parentNode->parentNode->parentNode->nodeName
+ )
+ ) {
+ $nodeValue = trim($node->nodeValue);
+
+ if (!empty($nodeValue)) {
+ $exerciseInfo['description'] = $node->nodeValue;
+ }
+ }
+ break;
+ }
}
}
diff --git a/main/gradebook/gradebook_view_result.php b/main/gradebook/gradebook_view_result.php
index ea0c278b2b3..d2c7398f43b 100755
--- a/main/gradebook/gradebook_view_result.php
+++ b/main/gradebook/gradebook_view_result.php
@@ -247,12 +247,7 @@
$values = $import_result_form->exportValues();
$file_type = $_POST['file_type'];
$file_name = $_FILES['import_file']['tmp_name'];
- if ($file_type == 'csv') {
- $results = Import :: csvToArray($file_name);
- } else {
- $results = parse_xml_data($file_name);
- }
-
+ $results = Import :: csvToArray($file_name);
$nr_results_added = 0;
foreach ($results as $index => $importedresult) {
//check username & score
diff --git a/main/gradebook/lib/GradebookUtils.php b/main/gradebook/lib/GradebookUtils.php
index 27e345a0269..f3a41c214fd 100644
--- a/main/gradebook/lib/GradebookUtils.php
+++ b/main/gradebook/lib/GradebookUtils.php
@@ -651,40 +651,6 @@ public static function character_data($parser, $data)
$current_value = $data;
}
- /**
- * XML-parser: handle end of element.
- */
- public static function element_end($parser, $data)
- {
- global $user;
- global $users;
- global $current_value;
- switch ($data) {
- case 'Result':
- $users[] = $user;
- break;
- default:
- $user[$data] = $current_value;
- break;
- }
- }
-
- /**
- * XML-parser: handle start of element.
- */
- public static function element_start($parser, $data)
- {
- global $user;
- global $current_tag;
- switch ($data) {
- case 'Result':
- $user = [];
- break;
- default:
- $current_tag = $data;
- }
- }
-
public static function overwritescore($resid, $importscore, $eval_max)
{
$result = Result::load($resid);
@@ -697,30 +663,6 @@ public static function overwritescore($resid, $importscore, $eval_max)
unset($result);
}
- /**
- * Read the XML-file.
- *
- * @param string $file Path to the XML-file
- *
- * @return array All user information read from the file
- */
- public static function parse_xml_data($file)
- {
- global $current_tag;
- global $current_value;
- global $user;
- global $users;
- $users = [];
- $parser = xml_parser_create();
- xml_set_element_handler($parser, 'element_start', 'element_end');
- xml_set_character_data_handler($parser, "character_data");
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
- xml_parse($parser, file_get_contents($file));
- xml_parser_free($parser);
-
- return $users;
- }
-
/**
* register user info about certificate.
*
diff --git a/main/gradebook/lib/fe/dataform.class.php b/main/gradebook/lib/fe/dataform.class.php
index 03f6a63b8de..c6d736f7d98 100755
--- a/main/gradebook/lib/fe/dataform.class.php
+++ b/main/gradebook/lib/fe/dataform.class.php
@@ -107,13 +107,16 @@ protected function build_import_form()
$this->addElement('hidden', 'formSent');
$this->addElement('header', get_lang('ImportFileLocation'));
$this->addElement('file', 'import_file', get_lang('Location'));
- $allowed_file_types = [
- 'xml',
- 'csv',
- ];
- //$this->addRule('file', get_lang('InvalidExtension') . ' (' . implode(',', $allowed_file_types) . ')', 'filetype', $allowed_file_types);
- $this->addElement('radio', 'file_type', get_lang('FileType'), 'CSV ('.get_lang('ExampleCSVFile').')', 'csv');
- $this->addElement('radio', 'file_type', null, 'XML ('.get_lang('ExampleXMLFile').')', 'xml');
+ $this->addElement(
+ 'radio',
+ 'file_type',
+ get_lang('FileType'),
+ 'CSV ('
+ .get_lang('ExampleCSVFile')
+ .')',
+ 'csv'
+ );
+ //$this->addElement('radio', 'file_type', null, 'XML ('.get_lang('ExampleXMLFile').')', 'xml');
$this->addElement('checkbox', 'overwrite', null, get_lang('OverwriteScores'));
$this->addElement('checkbox', 'ignoreerrors', null, get_lang('IgnoreErrors'));
$this->addButtonImport(get_lang('Ok'));
diff --git a/main/group/import.php b/main/group/import.php
index 81b167f0662..36e4232c4c5 100755
--- a/main/group/import.php
+++ b/main/group/import.php
@@ -38,7 +38,8 @@
null,
Display::url(
get_lang('ExampleCSVFile'),
- api_get_path(WEB_CODE_PATH).'group/example.csv'
+ api_get_path(WEB_CODE_PATH).'group/example.csv',
+ ['download' => true]
)
);
$form->addButtonImport(get_lang('Import'));
diff --git a/main/inc/lib/myspace.lib.php b/main/inc/lib/myspace.lib.php
index ed84487fb25..52f712026bc 100644
--- a/main/inc/lib/myspace.lib.php
+++ b/main/inc/lib/myspace.lib.php
@@ -2359,7 +2359,7 @@ public static function user_available_in_session($username, $course_list, $id_se
*
* @author Julio Montoya Armas
*/
- public function check_all_usernames($users, $course_list, $id_session)
+ public static function check_all_usernames($users, $course_list, $id_session)
{
$table_user = Database::get_main_table(TABLE_MAIN_USER);
$usernames = [];
@@ -2409,7 +2409,7 @@ public function check_all_usernames($users, $course_list, $id_session)
*
* @author Julio Montoya Armas
*/
- public function get_user_creator($users)
+ public static function get_user_creator($users)
{
$errors = [];
foreach ($users as $index => $user) {
@@ -2437,7 +2437,7 @@ public function get_user_creator($users)
*
* @param array $users list of users
*/
- public function validate_data($users, $id_session = null)
+ public static function validate_data($users, $id_session = null)
{
$errors = [];
$new_users = [];
@@ -2475,7 +2475,7 @@ public function validate_data($users, $id_session = null)
/**
* Adds missing user-information (which isn't required, like password, etc).
*/
- public function complete_missing_data($user)
+ public static function complete_missing_data($user)
{
// 1. Generate a password if it is necessary.
if (!isset($user['Password']) || strlen($user['Password']) == 0) {
@@ -2488,14 +2488,14 @@ public function complete_missing_data($user)
/**
* Saves imported data.
*/
- public function save_data($users, $course_list, $id_session)
+ public static function save_data($users, $course_list, $id_session)
{
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
$tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
$tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
$tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
- $id_session = intval($id_session);
+ $id_session = (int) $id_session;
$sendMail = $_POST['sendMail'] ? 1 : 0;
// Adding users to the platform.
@@ -2612,7 +2612,7 @@ public function save_data($users, $course_list, $id_session)
$addedto = get_lang('UserNotAdded');
}
- $registered_users .= UserManager::getUserProfileLink($userInfo)." - ".$addedto.'
';
+ $registered_users .= UserManager::getUserProfileLink($userInfo).' - '.$addedto.'
';
}
} else {
$i = 0;
@@ -2632,10 +2632,10 @@ public function save_data($users, $course_list, $id_session)
$addedto = get_lang('UserNotAdded');
}
$registered_users .= "".
- api_get_person_name($user['FirstName'], $user['LastName'])." - ".$addedto.'
';
+ Security::remove_XSS($userInfo['complete_user_name'])." - ".$addedto.'
';
}
}
- Display::addFlash(Display::return_message($registered_users));
+ Display::addFlash(Display::return_message($registered_users, 'normal',false));
header('Location: course.php?id_session='.$id_session);
exit;
}
@@ -2660,55 +2660,6 @@ public function parse_csv_data($file)
return $users;
}
- /**
- * XML-parser: the handler at the beginning of element.
- */
- public function element_start($parser, $data)
- {
- $data = api_utf8_decode($data);
- global $user;
- global $current_tag;
- switch ($data) {
- case 'Contact':
- $user = [];
- break;
- default:
- $current_tag = $data;
- }
- }
-
- /**
- * XML-parser: the handler at the end of element.
- */
- public function element_end($parser, $data)
- {
- $data = api_utf8_decode($data);
- global $user;
- global $users;
- global $current_value;
- global $purification_option_for_usernames;
- $user[$data] = $current_value;
- switch ($data) {
- case 'Contact':
- $user['UserName'] = UserManager::purify_username($user['UserName'], $purification_option_for_usernames);
- $users[] = $user;
- break;
- default:
- $user[$data] = $current_value;
- break;
- }
- }
-
- /**
- * XML-parser: the handler for character data.
- */
- public function character_data($parser, $data)
- {
- $data = trim(api_utf8_decode($data));
- global $current_value;
- $current_value = $data;
- }
-
/**
* Reads XML-file.
*
@@ -2716,21 +2667,25 @@ public function character_data($parser, $data)
*
* @return array All userinformation read from the file
*/
- public function parse_xml_data($file)
+ public static function parse_xml_data($file)
{
- global $current_tag;
- global $current_value;
- global $user;
- global $users;
- $users = [];
- $parser = xml_parser_create('UTF-8');
- xml_set_element_handler($parser, ['MySpace', 'element_start'], ['MySpace', 'element_end']);
- xml_set_character_data_handler($parser, "character_data");
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
- xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
- xml_parser_free($parser);
+ $crawler = new \Symfony\Component\DomCrawler\Crawler();
+ $crawler->addXmlContent(file_get_contents($file));
+ $crawler = $crawler->filter('Contacts > Contact ');
+ $array = [];
+ foreach ($crawler as $domElement) {
+ $row = [];
+ foreach ($domElement->childNodes as $node) {
+ if ($node->nodeName != '#text') {
+ $row[$node->nodeName] = $node->nodeValue;
+ }
+ }
+ if (!empty($row)) {
+ $array[] = $row;
+ }
+ }
- return $users;
+ return $array;
}
/**
diff --git a/main/lp/aicc.class.php b/main/lp/aicc.class.php
index 9fe1e570d3c..091216baccb 100755
--- a/main/lp/aicc.class.php
+++ b/main/lp/aicc.class.php
@@ -439,6 +439,7 @@ public function import_package($zip_file_info, $current_dir = '')
$files_found = [];
$subdir_isset = false;
// The following loop should be stopped as soon as we found the right config files (.crs, .au, .des and .cst).
+ $realFileSize = 0;
foreach ($zipContentArray as $thisContent) {
if (preg_match('~.(php.*|phtml)$~i', $thisContent['filename'])) {
// If a php file is found, do not authorize (security risk).
diff --git a/main/lp/scorm.class.php b/main/lp/scorm.class.php
index c372467c0dc..b36ce1f76be 100755
--- a/main/lp/scorm.class.php
+++ b/main/lp/scorm.class.php
@@ -1,6 +1,8 @@
manifest_encoding);
- $doc = new DOMDocument();
- $res = @$doc->loadXML($xml);
- if ($res === false) {
+
+ $crawler = new Crawler();
+ $crawler->addXmlContent($xml);
+
+ $xmlErrors = libxml_get_errors();
+
+ if (!empty($xmlErrors)) {
if ($this->debug > 0) {
error_log('New LP - In scorm::parse_manifest() - Exception thrown when loading '.$file.' in DOMDocument');
}
@@ -105,10 +111,11 @@ public function parse_manifest($file = '')
}
if ($this->debug > 1) {
- error_log('New LP - Called (encoding:'.$doc->xmlEncoding.' - saved: '.$this->manifest_encoding.')', 0);
+ error_log('New LP - Called (encoding:'.$this->manifest_encoding.' - saved: '.$this->manifest_encoding.')', 0);
}
- $root = $doc->documentElement;
+ $root = $crawler->getNode(0);
+
if ($root->hasAttributes()) {
$attributes = $root->attributes;
if ($attributes->length !== 0) {
@@ -220,7 +227,6 @@ public function parse_manifest($file = '')
}
}
}
- unset($doc);
// End parsing using PHP5 DOMXML methods.
} else {
if ($this->debug > 1) {
@@ -586,8 +592,8 @@ public function import_local_package($file_path, $currentDir = '')
/**
* Imports a zip file into the Chamilo structure.
*
- * @param string $zip_file_info Zip file info as given by $_FILES['userFile']
- * @param string $current_dir
+ * @param string $zipFileInfo Zip file info as given by $_FILES['userFile']
+ * @param string $currentDir
* @param array $courseInfo
* @param bool $updateDirContents
* @param learnpath $lpToCheck
@@ -595,55 +601,58 @@ public function import_local_package($file_path, $currentDir = '')
* @return string $current_dir Absolute path to the imsmanifest.xml file or empty string on error
*/
public function import_package(
- $zip_file_info,
- $current_dir = '',
+ $zipFileInfo,
+ $currentDir = '',
$courseInfo = [],
$updateDirContents = false,
$lpToCheck = null
) {
if ($this->debug > 0) {
error_log(
- 'In scorm::import_package('.print_r($zip_file_info, true).',"'.$current_dir.'") method'
+ 'In scorm::import_package('.print_r($zipFileInfo, true).',"'.$currentDir.'") method'
);
}
$courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
$maxFilledSpace = DocumentManager::get_course_quota($courseInfo['code']);
- $zip_file_path = $zip_file_info['tmp_name'];
- $zip_file_name = $zip_file_info['name'];
+ $zipFilePath = $zipFileInfo['tmp_name'];
+ $zipFileName = $zipFileInfo['name'];
if ($this->debug > 1) {
- error_log('New LP - import_package() - zip file path = '.$zip_file_path.', zip file name = '.$zip_file_name, 0);
+ error_log(
+ 'New LP - import_package() - zip file path = '.$zipFilePath.', zip file name = '.$zipFileName,
+ 0
+ );
}
- $course_rel_dir = api_get_course_path($courseInfo['code']).'/scorm'; // scorm dir web path starting from /courses
- $course_sys_dir = api_get_path(SYS_COURSE_PATH).$course_rel_dir; // Absolute system path for this course.
- $current_dir = api_replace_dangerous_char(trim($current_dir)); // Current dir we are in, inside scorm/
+ $courseRelDir = api_get_course_path($courseInfo['code']).'/scorm'; // scorm dir web path starting from /courses
+ $courseSysDir = api_get_path(SYS_COURSE_PATH).$courseRelDir; // Absolute system path for this course.
+ $currentDir = api_replace_dangerous_char(trim($currentDir)); // Current dir we are in, inside scorm/
if ($this->debug > 1) {
- error_log('New LP - import_package() - current_dir = '.$current_dir, 0);
+ error_log('New LP - import_package() - current_dir = '.$currentDir, 0);
}
// Get name of the zip file without the extension.
- $file_info = pathinfo($zip_file_name);
- $filename = $file_info['basename'];
- $extension = $file_info['extension'];
- $file_base_name = str_replace('.'.$extension, '', $filename); // Filename without its extension.
- $this->zipname = $file_base_name; // Save for later in case we don't have a title.
- $new_dir = api_replace_dangerous_char(trim($file_base_name));
- $this->subdir = $new_dir;
+ $fileInfo = pathinfo($zipFileName);
+ $filename = $fileInfo['basename'];
+ $extension = $fileInfo['extension'];
+ $fileBaseName = str_replace('.'.$extension, '', $filename); // Filename without its extension.
+ $this->zipname = $fileBaseName; // Save for later in case we don't have a title.
+ $newDir = api_replace_dangerous_char(trim($fileBaseName));
+ $this->subdir = $newDir;
if ($this->debug > 1) {
- error_log('New LP - Received zip file name: '.$zip_file_path);
+ error_log('New LP - Received zip file name: '.$zipFilePath);
error_log("New LP - subdir is first set to : ".$this->subdir);
- error_log("New LP - base file name is : ".$file_base_name);
+ error_log("New LP - base file name is : ".$fileBaseName);
}
- $zipFile = new PclZip($zip_file_path);
+ $zipFile = new PclZip($zipFilePath);
// Check the zip content (real size and file extension).
$zipContentArray = $zipFile->listContent();
- $package_type = '';
- $manifest_list = [];
+ $packageType = '';
+ $manifestList = [];
// The following loop should be stopped as soon as we found the right imsmanifest.xml (how to recognize it?).
$realFileSize = 0;
foreach ($zipContentArray as $thisContent) {
@@ -657,29 +666,29 @@ public function import_package(
error_log("New LP - subdir is now ".$this->subdir);
}
}
- $package_type = 'scorm';
- $manifest_list[] = $thisContent['filename'];
+ $packageType = 'scorm';
+ $manifestList[] = $thisContent['filename'];
}
$realFileSize += $thisContent['size'];
}
// Now get the shortest path (basically, the imsmanifest that is the closest to the root).
- $shortest_path = $manifest_list[0];
- $slash_count = substr_count($shortest_path, '/');
- foreach ($manifest_list as $manifest_path) {
- $tmp_slash_count = substr_count($manifest_path, '/');
- if ($tmp_slash_count < $slash_count) {
- $shortest_path = $manifest_path;
- $slash_count = $tmp_slash_count;
+ $shortestPath = $manifestList[0];
+ $slashCount = substr_count($shortestPath, '/');
+ foreach ($manifestList as $manifestPath) {
+ $tmpSlashCount = substr_count($manifestPath, '/');
+ if ($tmpSlashCount < $slashCount) {
+ $shortestPath = $manifestPath;
+ $slashCount = $tmpSlashCount;
}
}
- $this->subdir .= '/'.dirname($shortest_path); // Do not concatenate because already done above.
- $manifest = $shortest_path;
+ $this->subdir .= '/'.dirname($shortestPath); // Do not concatenate because already done above.
+ $manifest = $shortestPath;
if ($this->debug) {
- error_log("New LP - Package type is now: '$package_type'");
+ error_log("New LP - Package type is now: '$packageType'");
}
- if ($package_type == '') {
+ if ($packageType == '') {
Display::addFlash(
Display::return_message(get_lang('NotScormContent'))
);
@@ -687,7 +696,7 @@ public function import_package(
return false;
}
- if (!enough_size($realFileSize, $course_sys_dir, $maxFilledSpace)) {
+ if (!enough_size($realFileSize, $courseSysDir, $maxFilledSpace)) {
if ($this->debug > 1) {
error_log('New LP - Not enough space to store package');
}
@@ -700,20 +709,20 @@ public function import_package(
if ($updateDirContents && $lpToCheck) {
$originalPath = str_replace('/.', '', $lpToCheck->path);
- if ($originalPath != $new_dir) {
+ if ($originalPath != $newDir) {
Display::addFlash(Display::return_message(get_lang('FileError')));
return false;
}
}
- // It happens on Linux that $new_dir sometimes doesn't start with '/'
- if ($new_dir[0] != '/') {
- $new_dir = '/'.$new_dir;
+ // It happens on Linux that $newDir sometimes doesn't start with '/'
+ if ($newDir[0] != '/') {
+ $newDir = '/'.$newDir;
}
- if ($new_dir[strlen($new_dir) - 1] == '/') {
- $new_dir = substr($new_dir, 0, -1);
+ if ($newDir[strlen($newDir) - 1] == '/') {
+ $newDir = substr($newDir, 0, -1);
}
/* Uncompressing phase */
@@ -723,15 +732,18 @@ public function import_package(
- parse & change relative html links
- make sure the filenames are secure (filter funny characters or php extensions)
*/
- if (is_dir($course_sys_dir.$new_dir) ||
- @mkdir($course_sys_dir.$new_dir, api_get_permissions_for_new_directories())
+ if (is_dir($courseSysDir.$newDir) ||
+ @mkdir(
+ $courseSysDir.$newDir,
+ api_get_permissions_for_new_directories()
+ )
) {
// PHP method - slower...
if ($this->debug >= 1) {
- error_log('New LP - Changing dir to '.$course_sys_dir.$new_dir);
+ error_log('New LP - Changing dir to '.$courseSysDir.$newDir);
}
- $saved_dir = getcwd();
- chdir($course_sys_dir.$new_dir);
+ $savedDir = getcwd();
+ chdir($courseSysDir.$newDir);
$unzippingState = $zipFile->extract();
for ($j = 0; $j < count($unzippingState); $j++) {
@@ -743,34 +755,34 @@ public function import_package(
}
}
- if (!empty($new_dir)) {
- $new_dir = $new_dir.'/';
+ if (!empty($newDir)) {
+ $newDir = $newDir.'/';
}
// Rename files, for example with \\ in it.
if ($this->debug >= 1) {
- error_log('New LP - try to open: '.$course_sys_dir.$new_dir);
+ error_log('New LP - try to open: '.$courseSysDir.$newDir);
}
- if ($dir = @opendir($course_sys_dir.$new_dir)) {
+ if ($dir = @opendir($courseSysDir.$newDir)) {
if ($this->debug >= 1) {
- error_log('New LP - Opened dir '.$course_sys_dir.$new_dir);
+ error_log('New LP - Opened dir '.$courseSysDir.$newDir);
}
while ($file = readdir($dir)) {
if ($file != '.' && $file != '..') {
// TODO: RENAMING FILES CAN BE VERY DANGEROUS SCORM-WISE, avoid that as much as possible!
- //$safe_file = api_replace_dangerous_char($file, 'strict');
- $find_str = ['\\', '.php', '.phtml'];
- $repl_str = ['/', '.txt', '.txt'];
- $safe_file = str_replace($find_str, $repl_str, $file);
+ //$safeFile = api_replace_dangerous_char($file, 'strict');
+ $findStr = ['\\', '.php', '.phtml'];
+ $replStr = ['/', '.txt', '.txt'];
+ $safeFile = str_replace($findStr, $replStr, $file);
if ($this->debug >= 1) {
- error_log('Comparing: '.$safe_file);
+ error_log('Comparing: '.$safeFile);
error_log('and: '.$file);
}
- if ($safe_file != $file) {
- $mydir = dirname($course_sys_dir.$new_dir.$safe_file);
+ if ($safeFile != $file) {
+ $mydir = dirname($courseSysDir.$newDir.$safeFile);
if (!is_dir($mydir)) {
$mysubdirs = explode('/', $mydir);
$mybasedir = '/';
@@ -786,10 +798,11 @@ public function import_package(
}
}
}
- @rename($course_sys_dir.$new_dir.$file, $course_sys_dir.$new_dir.$safe_file);
+ @rename($courseSysDir.$newDir.$file, $courseSysDir.$newDir.$safeFile);
if ($this->debug >= 1) {
error_log(
- 'New LP - Renaming '.$course_sys_dir.$new_dir.$file.' to '.$course_sys_dir.$new_dir.$safe_file
+ 'New LP - Renaming '.$courseSysDir.$newDir.$file.' to '.$courseSysDir.$newDir
+ .$safeFile
);
}
}
@@ -797,18 +810,18 @@ public function import_package(
}
closedir($dir);
- chdir($saved_dir);
+ chdir($savedDir);
- api_chmod_R($course_sys_dir.$new_dir, api_get_permissions_for_new_directories());
+ api_chmod_R($courseSysDir.$newDir, api_get_permissions_for_new_directories());
if ($this->debug > 1) {
- error_log('New LP - changed back to init dir: '.$course_sys_dir.$new_dir);
+ error_log('New LP - changed back to init dir: '.$courseSysDir.$newDir);
}
}
} else {
return false;
}
- return $course_sys_dir.$new_dir.$manifest;
+ return $courseSysDir.$newDir.$manifest;
}
/**
diff --git a/main/mySpace/user_import.php b/main/mySpace/user_import.php
index d5032722956..bba9bbf0bfc 100755
--- a/main/mySpace/user_import.php
+++ b/main/mySpace/user_import.php
@@ -46,8 +46,8 @@
}
set_time_limit(0);
-
-if ($_POST['formSent'] && $_FILES['import_file']['size'] !== 0) {
+$errors = [];
+if (isset($_POST['formSent']) && $_POST['formSent'] && $_FILES['import_file']['size'] !== 0) {
$file_type = $_POST['file_type'];
$id_session = intval($_POST['id_session']);
if ($file_type == 'csv') {
@@ -76,19 +76,21 @@
MySpace::save_data($users, $course_list, $id_session);
}
} else {
- header('Location: course.php?id_session='.$id_session.'&action=error_message&message='.urlencode(get_lang('NoSessionId')));
+ Display::addFlash(Display::return_message(get_lang('NoSessionId'), 'warning'));
+ header('Location: course.php?id_session='.$id_session);
exit;
}
}
} else {
- header('Location: course.php?id_session='.$id_session.'&action=error_message&message='.urlencode(get_lang('NoUsersRead')));
+ Display::addFlash(Display::return_message(get_lang('NoUsersRead'), 'warning'));
+ header('Location: course.php?id_session='.$id_session);
exit;
}
}
Display :: display_header($tool_name);
-if ($_FILES['import_file']['size'] == 0 && $_POST) {
+if (isset($_FILES['import_file']) && $_FILES['import_file']['size'] == 0 && $_POST) {
echo Display::return_message(get_lang('ThisFieldIsRequired'), 'error');
}
@@ -110,8 +112,20 @@
$form->addRule('import_file', get_lang('ThisFieldIsRequired'), 'required');
$allowed_file_types = ['xml', 'csv'];
$form->addRule('import_file', get_lang('InvalidExtension').' ('.implode(',', $allowed_file_types).')', 'filetype', $allowed_file_types);
-$form->addElement('radio', 'file_type', get_lang('FileType'), 'XML ('.get_lang('ExampleXMLFile').')', 'xml');
-$form->addElement('radio', 'file_type', null, 'CSV ('.get_lang('ExampleCSVFile').')', 'csv');
+$form->addElement(
+ 'radio',
+ 'file_type',
+ get_lang('FileType'),
+ 'XML ('.get_lang('ExampleXMLFile').')',
+ 'xml'
+);
+$form->addElement(
+ 'radio',
+ 'file_type',
+ null,
+ 'CSV ('.get_lang('ExampleCSVFile').')',
+ 'csv'
+);
$form->addElement('radio', 'sendMail', get_lang('SendMailToUsers'), get_lang('Yes'), 1);
$form->addElement('radio', 'sendMail', null, get_lang('No'), 0);
$form->addElement('submit', 'submit', get_lang('Ok'));
diff --git a/main/session/session_import.php b/main/session/session_import.php
index 9238daab62a..f27dd633e63 100644
--- a/main/session/session_import.php
+++ b/main/session/session_import.php
@@ -482,7 +482,7 @@
Display::url(
get_lang('ExampleCSVFile'),
api_get_path(WEB_CODE_PATH).'admin/example_session.csv',
- ['target' => '_blank']
+ ['target' => '_blank', 'download' => null]
),
],
'CSV',
@@ -496,7 +496,7 @@
Display::url(
get_lang('ExampleXMLFile'),
api_get_path(WEB_CODE_PATH).'admin/example_session.xml',
- ['target' => '_blank']
+ ['target' => '_blank', 'download' => null]
),
],
'XML',