1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @copyright (c) 2001-2006 Universite catholique de Louvain (UCL) |
4
|
|
|
* |
5
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html (GPL) GENERAL PUBLIC LICENSE |
6
|
|
|
* |
7
|
|
|
* @package chamilo.exercise |
8
|
|
|
* |
9
|
|
|
* @author claro team <[email protected]> |
10
|
|
|
* @author Guillaume Lederer <[email protected]> |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* function to create a temporary directory (SAME AS IN MODULE ADMIN) |
15
|
|
|
*/ |
16
|
|
View Code Duplication |
function tempdir($dir, $prefix = 'tmp', $mode = 0777) |
|
|
|
|
17
|
|
|
{ |
18
|
|
|
if (substr($dir, -1) != '/') { |
19
|
|
|
$dir .= '/'; |
20
|
|
|
} |
21
|
|
|
|
22
|
|
|
do { |
23
|
|
|
$path = $dir.$prefix.mt_rand(0, 9999999); |
24
|
|
|
} while (!mkdir($path, $mode)); |
25
|
|
|
|
26
|
|
|
return $path; |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Unzip the exercise in the temp folder |
31
|
|
|
* @param string The path of the temporary directory where the exercise was uploaded and unzipped |
32
|
|
|
* @param string |
33
|
|
|
* @param string $baseWorkDir |
34
|
|
|
* @param string $uploadPath |
35
|
|
|
* @return bool |
36
|
|
|
*/ |
37
|
|
|
function get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath) |
|
|
|
|
38
|
|
|
{ |
39
|
|
|
$_course = api_get_course_info(); |
40
|
|
|
$_user = api_get_user_info(); |
41
|
|
|
|
42
|
|
|
//Check if the file is valid (not to big and exists) |
43
|
|
View Code Duplication |
if (!isset($_FILES['userFile']) || !is_uploaded_file($_FILES['userFile']['tmp_name'])) { |
44
|
|
|
// upload failed |
45
|
|
|
return false; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
if (preg_match('/.zip$/i', $_FILES['userFile']['name']) && |
49
|
|
|
handle_uploaded_document( |
50
|
|
|
$_course, |
51
|
|
|
$_FILES['userFile'], |
52
|
|
|
$baseWorkDir, |
53
|
|
|
$uploadPath, |
54
|
|
|
$_user['user_id'], |
55
|
|
|
0, |
56
|
|
|
null, |
57
|
|
|
1 |
58
|
|
|
) |
59
|
|
|
) { |
60
|
|
|
return true; |
61
|
|
|
} |
62
|
|
|
return false; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Imports an exercise in QTI format if the XML structure can be found in it |
67
|
|
|
* @param array $file |
68
|
|
|
* @return an array as a backlog of what was really imported, and error or debug messages to display |
69
|
|
|
*/ |
70
|
|
|
function import_exercise($file) |
71
|
|
|
{ |
72
|
|
|
global $exercise_info; |
73
|
|
|
global $element_pile; |
74
|
|
|
global $non_HTML_tag_to_avoid; |
75
|
|
|
global $record_item_body; |
76
|
|
|
// used to specify the question directory where files could be found in relation in any question |
77
|
|
|
global $questionTempDir; |
78
|
|
|
|
79
|
|
|
$archive_path = api_get_path(SYS_ARCHIVE_PATH) . 'qti2'; |
80
|
|
|
$baseWorkDir = $archive_path; |
81
|
|
|
|
82
|
|
|
if (!is_dir($baseWorkDir)) { |
83
|
|
|
mkdir($baseWorkDir, api_get_permissions_for_new_directories(), true); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
$uploadPath = '/'; |
87
|
|
|
|
88
|
|
|
// set some default values for the new exercise |
89
|
|
|
$exercise_info = array(); |
90
|
|
|
$exercise_info['name'] = preg_replace('/.zip$/i', '', $file); |
91
|
|
|
$exercise_info['question'] = array(); |
92
|
|
|
$element_pile = array(); |
93
|
|
|
|
94
|
|
|
// create parser and array to retrieve info from manifest |
95
|
|
|
$element_pile = array(); //pile to known the depth in which we are |
96
|
|
|
//$module_info = array (); //array to store the info we need |
97
|
|
|
|
98
|
|
|
// if file is not a .zip, then we cancel all |
99
|
|
|
|
100
|
|
|
if (!preg_match('/.zip$/i', $file)) { |
101
|
|
|
|
102
|
|
|
return 'UplZipCorrupt'; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
// unzip the uploaded file in a tmp directory |
106
|
|
|
if (!get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath)) { |
107
|
|
|
|
108
|
|
|
return 'UplZipCorrupt'; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
// find the different manifests for each question and parse them. |
112
|
|
|
|
113
|
|
|
$exerciseHandle = opendir($baseWorkDir); |
114
|
|
|
//$question_number = 0; |
115
|
|
|
$file_found = false; |
116
|
|
|
$operation = false; |
117
|
|
|
$result = false; |
118
|
|
|
$filePath = null; |
119
|
|
|
|
120
|
|
|
// parse every subdirectory to search xml question files |
121
|
|
|
while (false !== ($file = readdir($exerciseHandle))) { |
122
|
|
|
if (is_dir($baseWorkDir . '/' . $file) && $file != "." && $file != "..") { |
123
|
|
|
// Find each manifest for each question repository found |
124
|
|
|
$questionHandle = opendir($baseWorkDir . '/' . $file); |
125
|
|
View Code Duplication |
while (false !== ($questionFile = readdir($questionHandle))) { |
126
|
|
|
if (preg_match('/.xml$/i', $questionFile)) { |
127
|
|
|
$result = qti_parse_file($baseWorkDir, $file, $questionFile); |
128
|
|
|
$filePath = $baseWorkDir . $file; |
129
|
|
|
$file_found = true; |
130
|
|
|
} |
131
|
|
|
} |
132
|
|
|
} elseif (preg_match('/.xml$/i', $file)) { |
133
|
|
|
|
134
|
|
|
// Else ignore file |
135
|
|
|
$result = qti_parse_file($baseWorkDir, '', $file); |
136
|
|
|
$filePath = $baseWorkDir . '/' . $file; |
137
|
|
|
$file_found = true; |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
if (!$file_found) { |
142
|
|
|
|
143
|
|
|
return 'NoXMLFileFoundInTheZip'; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
if ($result == false) { |
147
|
|
|
|
148
|
|
|
return false; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
$doc = new DOMDocument(); |
152
|
|
|
$doc->load($filePath); |
153
|
|
|
|
154
|
|
|
// 1. Create exercise. |
155
|
|
|
$exercise = new Exercise(); |
156
|
|
|
$exercise->exercise = $exercise_info['name']; |
157
|
|
|
|
158
|
|
|
$exercise->save(); |
159
|
|
|
$last_exercise_id = $exercise->selectId(); |
160
|
|
|
if (!empty($last_exercise_id)) { |
161
|
|
|
// For each question found... |
162
|
|
|
foreach ($exercise_info['question'] as $question_array) { |
163
|
|
|
//2. Create question |
164
|
|
|
$question = new Ims2Question(); |
165
|
|
|
$question->type = $question_array['type']; |
166
|
|
|
$question->setAnswer(); |
167
|
|
|
$question->updateTitle(formatText($question_array['title'])); |
168
|
|
|
//$question->updateDescription($question_array['title']); |
169
|
|
|
$type = $question->selectType(); |
170
|
|
|
$question->type = constant($type); |
171
|
|
|
$question->save($last_exercise_id); |
172
|
|
|
$last_question_id = $question->selectId(); |
173
|
|
|
//3. Create answer |
174
|
|
|
$answer = new Answer($last_question_id); |
175
|
|
|
$answer->new_nbrAnswers = count($question_array['answer']); |
176
|
|
|
$totalCorrectWeight = 0; |
177
|
|
|
foreach ($question_array['answer'] as $key => $answers) { |
178
|
|
|
$split = explode('_', $key); |
179
|
|
|
$i = $split[1]; |
180
|
|
|
// Answer |
181
|
|
|
$answer->new_answer[$i] = formatText($answers['value']); |
182
|
|
|
// Comment |
183
|
|
|
$answer->new_comment[$i] = isset($answers['feedback']) ? formatText($answers['feedback']) : null; |
184
|
|
|
// Position |
185
|
|
|
$answer->new_position[$i] = $i; |
186
|
|
|
// Correct answers |
187
|
|
|
if (in_array($key, $question_array['correct_answers'])) { |
188
|
|
|
$answer->new_correct[$i] = 1; |
189
|
|
|
} else { |
190
|
|
|
$answer->new_correct[$i] = 0; |
191
|
|
|
} |
192
|
|
|
$answer->new_weighting[$i] = $question_array['weighting'][$key]; |
193
|
|
|
if ($answer->new_correct[$i]) { |
194
|
|
|
$totalCorrectWeight = $answer->new_weighting[$i]; |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
$question->updateWeighting($totalCorrectWeight); |
198
|
|
|
$question->save($last_exercise_id); |
199
|
|
|
$answer->save(); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
// delete the temp dir where the exercise was unzipped |
203
|
|
|
my_delete($baseWorkDir . $uploadPath); |
204
|
|
|
return $last_exercise_id; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
return false; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* We assume the file charset is UTF8 |
212
|
|
|
**/ |
213
|
|
|
function formatText($text) |
214
|
|
|
{ |
215
|
|
|
return api_html_entity_decode($text); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Parses a given XML file and fills global arrays with the elements |
220
|
|
|
* @param string $exercisePath |
221
|
|
|
* @param string $file |
222
|
|
|
* @param string $questionFile |
223
|
|
|
* @return bool |
224
|
|
|
*/ |
225
|
|
|
function qti_parse_file($exercisePath, $file, $questionFile) |
226
|
|
|
{ |
227
|
|
|
global $non_HTML_tag_to_avoid; |
228
|
|
|
global $record_item_body; |
229
|
|
|
global $questionTempDir; |
230
|
|
|
|
231
|
|
|
$questionTempDir = $exercisePath . '/' . $file . '/'; |
232
|
|
|
$questionFilePath = $questionTempDir . $questionFile; |
233
|
|
|
|
234
|
|
|
if (!($fp = fopen($questionFilePath, 'r'))) { |
235
|
|
|
Display::addFlash(Display::return_message(get_lang('Error opening question\'s XML file'), 'error')); |
236
|
|
|
|
237
|
|
|
return false; |
238
|
|
|
} else { |
239
|
|
|
$data = fread($fp, filesize($questionFilePath)); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
//parse XML question file |
243
|
|
|
$data = str_replace(array('<p>', '</p>', '<front>', '</front>'), '', $data); |
244
|
|
|
|
245
|
|
|
//used global variable start values declaration : |
246
|
|
|
|
247
|
|
|
$record_item_body = false; |
248
|
|
|
$non_HTML_tag_to_avoid = array( |
249
|
|
|
"SIMPLECHOICE", |
250
|
|
|
"CHOICEINTERACTION", |
251
|
|
|
"INLINECHOICEINTERACTION", |
252
|
|
|
"INLINECHOICE", |
253
|
|
|
"SIMPLEMATCHSET", |
254
|
|
|
"SIMPLEASSOCIABLECHOICE", |
255
|
|
|
"TEXTENTRYINTERACTION", |
256
|
|
|
"FEEDBACKINLINE", |
257
|
|
|
"MATCHINTERACTION", |
258
|
|
|
"ITEMBODY", |
259
|
|
|
"BR", |
260
|
|
|
"IMG" |
261
|
|
|
); |
262
|
|
|
|
263
|
|
|
$question_format_supported = true; |
264
|
|
|
|
265
|
|
|
$xml_parser = xml_parser_create(); |
266
|
|
|
xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, false); |
267
|
|
|
xml_set_element_handler($xml_parser, 'startElement', 'endElement'); |
268
|
|
|
xml_set_character_data_handler($xml_parser, 'elementData'); |
269
|
|
|
if (!xml_parse($xml_parser, $data, feof($fp))) { |
270
|
|
|
// if reading of the xml file in not successful : |
271
|
|
|
// set errorFound, set error msg, break while statement |
272
|
|
|
Display:: display_error_message(get_lang('Error reading XML file')); |
273
|
|
|
return false; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
//close file |
277
|
|
|
fclose($fp); |
278
|
|
|
if (!$question_format_supported) { |
279
|
|
|
Display::addFlash( |
280
|
|
|
Display::return_message( |
281
|
|
|
get_lang( |
282
|
|
|
'Unknown question format in file %file', |
283
|
|
|
array( |
284
|
|
|
'%file' => $questionFile, |
285
|
|
|
) |
286
|
|
|
), |
287
|
|
|
'error' |
288
|
|
|
) |
289
|
|
|
); |
290
|
|
|
return false; |
291
|
|
|
} |
292
|
|
|
return true; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Function used by the SAX xml parser when the parser meets a opening tag |
297
|
|
|
* |
298
|
|
|
* @param object $parser xml parser created with "xml_parser_create()" |
299
|
|
|
* @param string $name name of the element |
300
|
|
|
* @param array $attributes |
301
|
|
|
*/ |
302
|
|
|
function startElement($parser, $name, $attributes) |
303
|
|
|
{ |
304
|
|
|
global $element_pile; |
305
|
|
|
global $exercise_info; |
306
|
|
|
global $current_question_ident; |
307
|
|
|
global $current_answer_id; |
308
|
|
|
global $current_match_set; |
309
|
|
|
global $currentAssociableChoice; |
310
|
|
|
global $current_question_item_body; |
311
|
|
|
global $record_item_body; |
312
|
|
|
global $non_HTML_tag_to_avoid; |
313
|
|
|
global $current_inlinechoice_id; |
314
|
|
|
global $cardinality; |
315
|
|
|
global $questionTempDir; |
316
|
|
|
|
317
|
|
|
array_push($element_pile, $name); |
318
|
|
|
$current_element = end($element_pile); |
319
|
|
View Code Duplication |
if (sizeof($element_pile) >= 2) { |
320
|
|
|
$parent_element = $element_pile[sizeof($element_pile) - 2]; |
321
|
|
|
} else { |
322
|
|
|
$parent_element = ""; |
323
|
|
|
} |
324
|
|
View Code Duplication |
if (sizeof($element_pile) >= 3) { |
325
|
|
|
$grant_parent_element = $element_pile[sizeof($element_pile) - 3]; |
326
|
|
|
} else { |
327
|
|
|
$grant_parent_element = ""; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
if ($record_item_body) { |
331
|
|
|
|
332
|
|
|
if ((!in_array($current_element, $non_HTML_tag_to_avoid))) { |
333
|
|
|
$current_question_item_body .= "<" . $name; |
334
|
|
|
foreach ($attributes as $attribute_name => $attribute_value) { |
335
|
|
|
$current_question_item_body .= " " . $attribute_name . "=\"" . $attribute_value . "\""; |
336
|
|
|
} |
337
|
|
|
$current_question_item_body .= ">"; |
338
|
|
|
} else { |
339
|
|
|
//in case of FIB question, we replace the IMS-QTI tag b y the correct answer between "[" "]", |
340
|
|
|
//we first save with claroline tags ,then when the answer will be parsed, the claroline tags will be replaced |
341
|
|
|
|
342
|
|
|
if ($current_element == 'INLINECHOICEINTERACTION') { |
343
|
|
|
|
344
|
|
|
$current_question_item_body .= "**claroline_start**" . $attributes['RESPONSEIDENTIFIER'] . "**claroline_end**"; |
345
|
|
|
} |
346
|
|
|
if ($current_element == 'TEXTENTRYINTERACTION') { |
347
|
|
|
$correct_answer_value = $exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id]; |
348
|
|
|
$current_question_item_body .= "[" . $correct_answer_value . "]"; |
349
|
|
|
|
350
|
|
|
} |
351
|
|
|
if ($current_element == 'BR') { |
352
|
|
|
$current_question_item_body .= "<br />"; |
353
|
|
|
} |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
switch ($current_element) { |
357
|
|
|
case 'ASSESSMENTITEM': |
358
|
|
|
//retrieve current question |
359
|
|
|
$current_question_ident = $attributes['IDENTIFIER']; |
360
|
|
|
$exercise_info['question'][$current_question_ident] = array(); |
361
|
|
|
$exercise_info['question'][$current_question_ident]['answer'] = array(); |
362
|
|
|
$exercise_info['question'][$current_question_ident]['correct_answers'] = array(); |
363
|
|
|
$exercise_info['question'][$current_question_ident]['title'] = $attributes['TITLE']; |
364
|
|
|
$exercise_info['question'][$current_question_ident]['tempdir'] = $questionTempDir; |
365
|
|
|
break; |
366
|
|
|
case 'SECTION': |
367
|
|
|
//retrieve exercise name |
368
|
|
|
if (isset($attributes['TITLE']) && !empty($attributes['TITLE'])) { |
369
|
|
|
$exercise_info['name'] = $attributes['TITLE']; |
370
|
|
|
} |
371
|
|
|
break; |
372
|
|
|
case 'RESPONSEDECLARATION': |
373
|
|
|
// Retrieve question type |
374
|
|
View Code Duplication |
if ("multiple" == $attributes['CARDINALITY']) { |
375
|
|
|
$exercise_info['question'][$current_question_ident]['type'] = 'MCMA'; |
376
|
|
|
$cardinality = 'multiple'; |
377
|
|
|
} |
378
|
|
View Code Duplication |
if ("single" == $attributes['CARDINALITY']) { |
379
|
|
|
$exercise_info['question'][$current_question_ident]['type'] = 'MCUA'; |
380
|
|
|
$cardinality = 'single'; |
381
|
|
|
} |
382
|
|
|
//needed for FIB |
383
|
|
|
$current_answer_id = $attributes['IDENTIFIER']; |
384
|
|
|
break; |
385
|
|
|
case 'INLINECHOICEINTERACTION': |
386
|
|
|
$exercise_info['question'][$current_question_ident]['type'] = 'FIB'; |
387
|
|
|
$exercise_info['question'][$current_question_ident]['subtype'] = 'LISTBOX_FILL'; |
388
|
|
|
$current_answer_id = $attributes['RESPONSEIDENTIFIER']; |
389
|
|
|
break; |
390
|
|
|
case 'INLINECHOICE': |
391
|
|
|
$current_inlinechoice_id = $attributes['IDENTIFIER']; |
392
|
|
|
break; |
393
|
|
|
case 'TEXTENTRYINTERACTION': |
394
|
|
|
$exercise_info['question'][$current_question_ident]['type'] = 'FIB'; |
395
|
|
|
$exercise_info['question'][$current_question_ident]['subtype'] = 'TEXTFIELD_FILL'; |
396
|
|
|
$exercise_info['question'][$current_question_ident]['response_text'] = $current_question_item_body; |
397
|
|
|
//replace claroline tags |
398
|
|
|
break; |
399
|
|
|
case 'MATCHINTERACTION': |
400
|
|
|
$exercise_info['question'][$current_question_ident]['type'] = 'MATCHING'; |
401
|
|
|
break; |
402
|
|
|
case 'SIMPLEMATCHSET': |
403
|
|
|
if (!isset($current_match_set)) { |
404
|
|
|
$current_match_set = 1; |
405
|
|
|
} else { |
406
|
|
|
$current_match_set++; |
407
|
|
|
} |
408
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_match_set] = array(); |
409
|
|
|
break; |
410
|
|
|
case 'SIMPLEASSOCIABLECHOICE': |
411
|
|
|
$currentAssociableChoice = $attributes['IDENTIFIER']; |
412
|
|
|
break; |
413
|
|
|
//retrieve answers id for MCUA and MCMA questions |
414
|
|
|
case 'SIMPLECHOICE': |
415
|
|
|
$current_answer_id = $attributes['IDENTIFIER']; |
416
|
|
|
if (!isset($exercise_info['question'][$current_question_ident]['answer'][$current_answer_id])) { |
417
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_answer_id] = array(); |
418
|
|
|
} |
419
|
|
|
break; |
420
|
|
|
case 'MAPENTRY': |
421
|
|
|
if ($parent_element == "MAPPING") { |
422
|
|
|
$answer_id = $attributes['MAPKEY']; |
423
|
|
View Code Duplication |
if (!isset ($exercise_info['question'][$current_question_ident]['weighting'])) { |
424
|
|
|
$exercise_info['question'][$current_question_ident]['weighting'] = array(); |
425
|
|
|
} |
426
|
|
|
$exercise_info['question'][$current_question_ident]['weighting'][$answer_id] = $attributes['MAPPEDVALUE']; |
427
|
|
|
} |
428
|
|
|
break; |
429
|
|
|
case 'MAPPING': |
|
|
|
|
430
|
|
|
if (isset ($attributes['DEFAULTVALUE'])) { |
431
|
|
|
$exercise_info['question'][$current_question_ident]['default_weighting'] = $attributes['DEFAULTVALUE']; |
432
|
|
|
} |
433
|
|
|
case 'ITEMBODY': |
434
|
|
|
$record_item_body = true; |
435
|
|
|
$current_question_item_body = ''; |
436
|
|
|
break; |
437
|
|
|
case 'IMG': |
438
|
|
|
$exercise_info['question'][$current_question_ident]['attached_file_url'] = $attributes['SRC']; |
439
|
|
|
break; |
440
|
|
|
} |
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
/** |
444
|
|
|
* Function used by the SAX xml parser when the parser meets a closing tag |
445
|
|
|
* |
446
|
|
|
* @param $parser xml parser created with "xml_parser_create()" |
447
|
|
|
* @param $name name of the element |
448
|
|
|
*/ |
449
|
|
|
function endElement($parser, $name) |
450
|
|
|
{ |
451
|
|
|
global $element_pile; |
452
|
|
|
global $exercise_info; |
453
|
|
|
global $current_question_ident; |
454
|
|
|
global $record_item_body; |
455
|
|
|
global $current_question_item_body; |
456
|
|
|
global $non_HTML_tag_to_avoid; |
457
|
|
|
global $cardinality; |
458
|
|
|
|
459
|
|
|
$current_element = end($element_pile); |
460
|
|
|
|
461
|
|
|
//treat the record of the full content of itembody tag : |
462
|
|
|
|
463
|
|
|
if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) { |
464
|
|
|
$current_question_item_body .= "</" . $name . ">"; |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
switch ($name) { |
468
|
|
|
case 'ITEMBODY': |
469
|
|
|
$record_item_body = false; |
470
|
|
|
if ($exercise_info['question'][$current_question_ident]['type'] == 'FIB') { |
471
|
|
|
$exercise_info['question'][$current_question_ident]['response_text'] = $current_question_item_body; |
472
|
|
|
} else { |
473
|
|
|
$exercise_info['question'][$current_question_ident]['statement'] = $current_question_item_body; |
474
|
|
|
} |
475
|
|
|
break; |
476
|
|
|
} |
477
|
|
|
array_pop($element_pile); |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
/** |
481
|
|
|
* @param $parser |
482
|
|
|
* @param $data |
483
|
|
|
*/ |
484
|
|
|
function elementData($parser, $data) |
485
|
|
|
{ |
486
|
|
|
global $element_pile; |
487
|
|
|
global $exercise_info; |
488
|
|
|
global $current_question_ident; |
489
|
|
|
global $current_answer_id; |
490
|
|
|
global $current_match_set; |
491
|
|
|
global $currentAssociableChoice; |
492
|
|
|
global $current_question_item_body; |
493
|
|
|
global $record_item_body; |
494
|
|
|
global $non_HTML_tag_to_avoid; |
495
|
|
|
global $current_inlinechoice_id; |
496
|
|
|
global $cardinality; |
497
|
|
|
|
498
|
|
|
$current_element = end($element_pile); |
499
|
|
View Code Duplication |
if (sizeof($element_pile) >= 2) { |
500
|
|
|
$parent_element = $element_pile[sizeof($element_pile) - 2]; |
501
|
|
|
} else { |
502
|
|
|
$parent_element = ""; |
503
|
|
|
} |
504
|
|
View Code Duplication |
if (sizeof($element_pile) >= 3) { |
505
|
|
|
$grant_parent_element = $element_pile[sizeof($element_pile) - 3]; |
506
|
|
|
} else { |
507
|
|
|
$grant_parent_element = ""; |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
//treat the record of the full content of itembody tag (needed for question statment and/or FIB text: |
511
|
|
|
|
512
|
|
|
if ($record_item_body && (!in_array($current_element, $non_HTML_tag_to_avoid))) { |
513
|
|
|
$current_question_item_body .= $data; |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
switch ($current_element) { |
517
|
|
View Code Duplication |
case 'SIMPLECHOICE': |
518
|
|
|
if (!isset ($exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'])) { |
519
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'] = trim($data); |
520
|
|
|
} else { |
521
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['value'] .= '' . trim($data); |
522
|
|
|
} |
523
|
|
|
break; |
524
|
|
View Code Duplication |
case 'FEEDBACKINLINE': |
525
|
|
|
if (!isset ($exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['feedback'])) { |
526
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['feedback'] = trim($data); |
527
|
|
|
} else { |
528
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_answer_id]['feedback'] .= ' ' . trim($data); |
529
|
|
|
} |
530
|
|
|
break; |
531
|
|
|
case 'SIMPLEASSOCIABLECHOICE': |
532
|
|
|
$exercise_info['question'][$current_question_ident]['answer'][$current_match_set][$currentAssociableChoice] = trim($data); |
533
|
|
|
break; |
534
|
|
|
case 'VALUE': |
535
|
|
|
if ($parent_element == "CORRECTRESPONSE") { |
536
|
|
|
if ($cardinality == "single") { |
537
|
|
|
$exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id] = $data; |
538
|
|
|
} else { |
539
|
|
|
$exercise_info['question'][$current_question_ident]['correct_answers'][] = $data; |
540
|
|
|
} |
541
|
|
|
} |
542
|
|
|
break; |
543
|
|
|
case 'ITEMBODY': |
544
|
|
|
$current_question_item_body .= $data; |
545
|
|
|
break; |
546
|
|
|
case 'INLINECHOICE': |
547
|
|
|
// if this is the right answer, then we must replace the claroline tags in the FIB text bye the answer between "[" and "]" : |
548
|
|
|
$answer_identifier = $exercise_info['question'][$current_question_ident]['correct_answers'][$current_answer_id]; |
549
|
|
|
if ($current_inlinechoice_id == $answer_identifier) { |
550
|
|
|
$current_question_item_body = str_replace( |
551
|
|
|
"**claroline_start**" . $current_answer_id . "**claroline_end**", |
552
|
|
|
"[" . $data . "]", |
553
|
|
|
$current_question_item_body |
554
|
|
|
); |
555
|
|
|
} else { |
556
|
|
View Code Duplication |
if (!isset ($exercise_info['question'][$current_question_ident]['wrong_answers'])) { |
557
|
|
|
$exercise_info['question'][$current_question_ident]['wrong_answers'] = array(); |
558
|
|
|
} |
559
|
|
|
$exercise_info['question'][$current_question_ident]['wrong_answers'][] = $data; |
560
|
|
|
} |
561
|
|
|
break; |
562
|
|
|
} |
563
|
|
|
} |
564
|
|
|
|
This check looks for functions that have already been defined in other files.
Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the
@ignore
annotation.See also the PhpDoc documentation for @ignore.