1 | <?php |
||
2 | |||
3 | /* For licensing terms, see /license.txt */ |
||
4 | |||
5 | use Chamilo\CoreBundle\Entity\TrackEExerciseConfirmation; |
||
6 | use Chamilo\CoreBundle\Entity\TrackEExercises; |
||
7 | use Chamilo\CourseBundle\Entity\CQuizQuestion; |
||
8 | use ChamiloSession as Session; |
||
9 | |||
10 | require_once __DIR__.'/../global.inc.php'; |
||
11 | $current_course_tool = TOOL_QUIZ; |
||
12 | $debug = false; |
||
13 | // Check if the user has access to the contextual course/session |
||
14 | api_protect_course_script(true); |
||
15 | |||
16 | $action = $_REQUEST['a']; |
||
17 | $course_id = api_get_course_int_id(); |
||
18 | $session_id = isset($_REQUEST['session_id']) ? (int) $_REQUEST['session_id'] : api_get_session_id(); |
||
19 | $course_code = isset($_REQUEST['cidReq']) ? $_REQUEST['cidReq'] : api_get_course_id(); |
||
20 | $currentUserId = api_get_user_id(); |
||
21 | $exeId = isset($_REQUEST['exe_id']) ? $_REQUEST['exe_id'] : 0; |
||
22 | |||
23 | switch ($action) { |
||
24 | case 'get_exercise_by_course': |
||
25 | $course_id = (isset($_GET['course_id']) && !empty($_GET['course_id'])) ? (int) $_GET['course_id'] : 0; |
||
26 | $session_id = (!empty($_GET['session_id'])) ? (int) $_GET['session_id'] : 0; |
||
27 | $data = []; |
||
28 | $onlyActiveExercises = !(api_is_platform_admin(true) || api_is_course_admin()); |
||
29 | $results = ExerciseLib::get_all_exercises_for_course_id( |
||
30 | null, |
||
31 | $session_id, |
||
32 | $course_id, |
||
33 | $onlyActiveExercises |
||
34 | ); |
||
35 | |||
36 | if (!empty($results)) { |
||
37 | foreach ($results as $exercise) { |
||
38 | $data[] = ['id' => $exercise['iid'], 'text' => html_entity_decode($exercise['title'])]; |
||
39 | } |
||
40 | } |
||
41 | |||
42 | echo json_encode($data); |
||
43 | break; |
||
44 | case 'update_duration': |
||
45 | if (Session::read('login_as')) { |
||
46 | if ($debug) { |
||
47 | error_log("User is 'login as' don't update duration time."); |
||
48 | } |
||
49 | exit; |
||
50 | } |
||
51 | |||
52 | if (empty($exeId)) { |
||
53 | if ($debug) { |
||
54 | error_log('Exe id not provided.'); |
||
55 | } |
||
56 | exit; |
||
57 | } |
||
58 | |||
59 | /** @var Exercise $exerciseInSession */ |
||
60 | $exerciseInSession = Session::read('objExercise'); |
||
61 | |||
62 | if (empty($exerciseInSession)) { |
||
63 | if ($debug) { |
||
64 | error_log('Exercise obj not provided.'); |
||
65 | } |
||
66 | exit; |
||
67 | } |
||
68 | |||
69 | // If exercise was updated x seconds before, then don't updated duration. |
||
70 | $onlyUpdateValue = 10; |
||
71 | |||
72 | $em = Database::getManager(); |
||
73 | /** @var TrackEExercises $attempt */ |
||
74 | $attempt = $em->getRepository('ChamiloCoreBundle:TrackEExercises')->find($exeId); |
||
75 | |||
76 | if (empty($attempt)) { |
||
77 | if ($debug) { |
||
78 | error_log("Attempt #$exeId doesn't exists."); |
||
79 | } |
||
80 | exit; |
||
81 | } |
||
82 | |||
83 | $nowObject = api_get_utc_datetime(null, false, true); |
||
84 | $now = $nowObject->getTimestamp(); |
||
85 | $exerciseId = $attempt->getExeExoId(); |
||
86 | $userId = $attempt->getExeUserId(); |
||
87 | |||
88 | if ($userId != $currentUserId) { |
||
89 | if ($debug) { |
||
90 | error_log("User $currentUserId trying to change time for user $userId"); |
||
91 | } |
||
92 | exit; |
||
93 | } |
||
94 | |||
95 | if ($exerciseInSession->iid != $exerciseId) { |
||
96 | if ($debug) { |
||
97 | error_log("Cannot update, exercise are different."); |
||
98 | } |
||
99 | exit; |
||
100 | } |
||
101 | |||
102 | if ($attempt->getStatus() != 'incomplete') { |
||
103 | if ($debug) { |
||
104 | error_log('Cannot update exercise is already completed.'); |
||
105 | } |
||
106 | exit; |
||
107 | } |
||
108 | |||
109 | // Check if we are dealing with the same exercise. |
||
110 | $timeWithOutUpdate = $now - $attempt->getExeDate()->getTimestamp(); |
||
111 | if ($timeWithOutUpdate > $onlyUpdateValue) { |
||
112 | $key = ExerciseLib::get_time_control_key( |
||
113 | $exerciseId, |
||
114 | $attempt->getOrigLpId(), |
||
115 | $attempt->getOrigLpItemId() |
||
116 | ); |
||
117 | $durationFromObject = $attempt->getExeDuration(); |
||
118 | $previousTime = Session::read('duration_time_previous'); |
||
119 | if (isset($previousTime[$key]) && |
||
120 | !empty($previousTime[$key]) |
||
121 | ) { |
||
122 | $sessionTime = $previousTime[$key]; |
||
123 | $duration = $sessionTime = $now - $sessionTime; |
||
124 | if (!empty($durationFromObject)) { |
||
125 | $duration += $durationFromObject; |
||
126 | } |
||
127 | $duration = (int) $duration; |
||
128 | if (!empty($duration)) { |
||
129 | if ($debug) { |
||
130 | error_log("Exe_id: #".$exeId); |
||
131 | error_log("Key: $key"); |
||
132 | error_log("Exercise to update: #$exerciseId of user: #$userId"); |
||
133 | error_log("Duration time found in DB before update: $durationFromObject"); |
||
134 | error_log("Current spent time $sessionTime before an update"); |
||
135 | error_log("Accumulate duration to save in DB: $duration"); |
||
136 | error_log("End date (UTC) before update: ".$attempt->getExeDate()->format('Y-m-d H:i:s')); |
||
137 | error_log("End date (UTC) to be save in DB: ".$nowObject->format('Y-m-d H:i:s')); |
||
138 | } |
||
139 | $attempt |
||
140 | ->setExeDuration($duration) |
||
141 | ->setExeDate($nowObject); |
||
142 | $em->merge($attempt); |
||
143 | $em->flush(); |
||
144 | } |
||
145 | } else { |
||
146 | if ($debug) { |
||
147 | error_log("Nothing to update, 'duration_time_previous' session not set"); |
||
148 | error_log("Key: $key"); |
||
149 | } |
||
150 | } |
||
151 | } else { |
||
152 | if ($debug) { |
||
153 | error_log("Can't update, time was already updated $timeWithOutUpdate seconds ago"); |
||
154 | } |
||
155 | } |
||
156 | |||
157 | break; |
||
158 | case 'get_live_stats': |
||
159 | if (!api_is_allowed_to_edit(null, true)) { |
||
160 | break; |
||
161 | } |
||
162 | |||
163 | // 1. Setting variables needed by jqgrid |
||
164 | $exercise_id = (int) $_GET['exercise_id']; |
||
165 | $page = (int) $_REQUEST['page']; //page |
||
166 | $limit = (int) $_REQUEST['rows']; //quantity of rows |
||
167 | $sidx = $_REQUEST['sidx']; //index to filter |
||
168 | $sord = $_REQUEST['sord']; //asc or desc |
||
169 | |||
170 | if (!in_array($sidx, ['firstname', 'lastname', 'start_date'])) { |
||
171 | $sidx = 1; |
||
172 | } |
||
173 | |||
174 | if (!in_array($sord, ['asc', 'desc'])) { |
||
175 | $sord = 'desc'; |
||
176 | } |
||
177 | // get index row - i.e. user click to sort $sord = $_GET['sord']; |
||
178 | // get the direction |
||
179 | if (!$sidx) { |
||
180 | $sidx = 1; |
||
181 | } |
||
182 | |||
183 | $track_exercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); |
||
184 | $user_table = Database::get_main_table(TABLE_MAIN_USER); |
||
185 | $track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); |
||
186 | |||
187 | $minutes = (int) $_REQUEST['minutes']; |
||
188 | $now = time() - 60 * $minutes; |
||
189 | $now = api_get_utc_datetime($now); |
||
190 | |||
191 | $where_condition = " orig_lp_id = 0 AND exe_exo_id = $exercise_id AND start_date > '$now' "; |
||
192 | $sql = "SELECT COUNT(DISTINCT exe_id) |
||
193 | FROM $track_exercise |
||
194 | WHERE $where_condition "; |
||
195 | $result = Database::query($sql); |
||
196 | $count = Database::fetch_row($result); |
||
197 | $count = $count[0]; |
||
198 | |||
199 | //3. Calculating first, end, etc |
||
200 | $total_pages = 0; |
||
201 | if ($count > 0) { |
||
202 | if (!empty($limit)) { |
||
203 | $total_pages = ceil($count / $limit); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | if ($page > $total_pages) { |
||
208 | $page = $total_pages; |
||
209 | } |
||
210 | |||
211 | $start = $limit * $page - $limit; |
||
212 | if ($start < 0) { |
||
213 | $start = 0; |
||
214 | } |
||
215 | |||
216 | $sql = "SELECT |
||
217 | exe_id, |
||
218 | exe_user_id, |
||
219 | firstname, |
||
220 | lastname, |
||
221 | aa.status, |
||
222 | start_date, |
||
223 | exe_result, |
||
224 | exe_weighting, |
||
225 | exe_result/exe_weighting as score, |
||
226 | exe_duration, |
||
227 | questions_to_check, |
||
228 | orig_lp_id |
||
229 | FROM $user_table u |
||
230 | INNER JOIN ( |
||
231 | SELECT |
||
232 | t.exe_id, |
||
233 | t.exe_user_id, |
||
234 | status, |
||
235 | start_date, |
||
236 | exe_result, |
||
237 | exe_weighting, |
||
238 | exe_result/exe_weighting as score, |
||
239 | exe_duration, |
||
240 | questions_to_check, |
||
241 | orig_lp_id |
||
242 | FROM $track_exercise t |
||
243 | LEFT JOIN $track_attempt a |
||
244 | ON (a.exe_id = t.exe_id AND t.exe_user_id = a.user_id) |
||
245 | WHERE t.status = 'incomplete' AND $where_condition |
||
246 | GROUP BY exe_user_id |
||
247 | ) as aa |
||
248 | ON aa.exe_user_id = user_id |
||
249 | ORDER BY $sidx $sord |
||
250 | LIMIT $start, $limit"; |
||
251 | |||
252 | $result = Database::query($sql); |
||
253 | $results = []; |
||
254 | while ($row = Database::fetch_array($result, 'ASSOC')) { |
||
255 | $results[] = $row; |
||
256 | } |
||
257 | |||
258 | $oExe = new Exercise(); |
||
259 | $oExe->read($exercise_id); |
||
260 | |||
261 | $response = new stdClass(); |
||
262 | $response->page = $page; |
||
263 | $response->total = $total_pages; |
||
264 | $response->records = $count; |
||
265 | $i = 0; |
||
266 | |||
267 | if (!empty($results)) { |
||
268 | foreach ($results as $row) { |
||
269 | $sql = "SELECT SUM(count_question_id) as count_question_id |
||
270 | FROM ( |
||
271 | SELECT 1 as count_question_id |
||
272 | FROM $track_attempt a |
||
273 | WHERE |
||
274 | user_id = {$row['exe_user_id']} AND |
||
275 | exe_id = {$row['exe_id']} |
||
276 | GROUP by question_id |
||
277 | ) as count_table"; |
||
278 | $result_count = Database::query($sql); |
||
279 | $count_questions = Database::fetch_array( |
||
280 | $result_count, |
||
281 | 'ASSOC' |
||
282 | ); |
||
283 | $count_questions = $count_questions['count_question_id']; |
||
284 | |||
285 | $row['count_questions'] = $count_questions; |
||
286 | |||
287 | $response->rows[$i]['id'] = $row['exe_id']; |
||
288 | if (!empty($oExe->expired_time)) { |
||
289 | $remaining = strtotime($row['start_date']) + |
||
290 | ($oExe->expired_time * 60) - |
||
291 | strtotime(api_get_utc_datetime(time())); |
||
292 | $h = floor($remaining / 3600); |
||
293 | $m = floor(($remaining - ($h * 3600)) / 60); |
||
294 | $s = ($remaining - ($h * 3600) - ($m * 60)); |
||
295 | $timeInfo = api_convert_and_format_date( |
||
296 | $row['start_date'], |
||
297 | DATE_TIME_FORMAT_LONG |
||
298 | ).' ['.($h > 0 ? $h.':' : '').sprintf("%02d", $m).':'.sprintf("%02d", $s).']'; |
||
299 | } else { |
||
300 | $timeInfo = api_convert_and_format_date( |
||
301 | $row['start_date'], |
||
302 | DATE_TIME_FORMAT_LONG |
||
303 | ); |
||
304 | } |
||
305 | $array = [ |
||
306 | $row['firstname'], |
||
307 | $row['lastname'], |
||
308 | $timeInfo, |
||
309 | $row['count_questions'], |
||
310 | round($row['score'] * 100).'%', |
||
311 | ]; |
||
312 | $response->rows[$i]['cell'] = $array; |
||
313 | $i++; |
||
314 | } |
||
315 | } |
||
316 | echo json_encode($response); |
||
317 | break; |
||
318 | case 'update_exercise_list_order': |
||
319 | if (api_is_allowed_to_edit(null, true)) { |
||
320 | $new_list = $_REQUEST['exercise_list']; |
||
321 | $table = Database::get_course_table(TABLE_QUIZ_ORDER); |
||
322 | $counter = 1; |
||
323 | //Drop all |
||
324 | $sql = "DELETE FROM $table WHERE session_id = $session_id AND c_id = $course_id"; |
||
325 | Database::query($sql); |
||
326 | // Insert all |
||
327 | foreach ($new_list as $new_order_id) { |
||
328 | Database::insert( |
||
329 | $table, |
||
330 | [ |
||
331 | 'exercise_order' => $counter, |
||
332 | 'session_id' => $session_id, |
||
333 | 'exercise_id' => (int) $new_order_id, |
||
334 | 'c_id' => $course_id, |
||
335 | ] |
||
336 | ); |
||
337 | $counter++; |
||
338 | } |
||
339 | echo Display::return_message(get_lang('Saved'), 'confirmation'); |
||
340 | } |
||
341 | break; |
||
342 | case 'update_question_order': |
||
343 | $course_info = api_get_course_info_by_id($course_id); |
||
344 | $course_id = $course_info['real_id']; |
||
345 | $exercise_id = isset($_REQUEST['exercise_id']) ? (int) $_REQUEST['exercise_id'] : null; |
||
346 | |||
347 | if (empty($exercise_id)) { |
||
348 | return Display::return_message(get_lang('Error'), 'error'); |
||
349 | } |
||
350 | if (api_is_allowed_to_edit(null, true)) { |
||
351 | $new_question_list = $_POST['question_id_list']; |
||
352 | $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); |
||
353 | $counter = 1; |
||
354 | foreach ($new_question_list as $new_order_id) { |
||
355 | Database::update( |
||
356 | $TBL_QUESTIONS, |
||
357 | ['question_order' => $counter], |
||
358 | [ |
||
359 | 'question_id = ? AND c_id = ? AND exercice_id = ? ' => [ |
||
360 | (int) $new_order_id, |
||
361 | $course_id, |
||
362 | $exercise_id, |
||
363 | ], |
||
364 | ] |
||
365 | ) |
||
366 | ; |
||
367 | $counter++; |
||
368 | } |
||
369 | echo Display::return_message(get_lang('Saved'), 'confirmation'); |
||
370 | } |
||
371 | break; |
||
372 | case 'add_question_to_reminder': |
||
373 | /** @var Exercise $objExercise */ |
||
374 | $objExercise = Session::read('objExercise'); |
||
375 | |||
376 | if (empty($objExercise) || empty($exeId)) { |
||
377 | echo 0; |
||
378 | exit; |
||
379 | } |
||
380 | |||
381 | $option = isset($_GET['option']) ? $_GET['option'] : ''; |
||
382 | switch ($option) { |
||
383 | case 'add_all': |
||
384 | $questionListInSession = Session::read('questionList'); |
||
385 | $objExercise->addAllQuestionToRemind($exeId, $questionListInSession); |
||
386 | break; |
||
387 | case 'remove_all': |
||
388 | $objExercise->removeAllQuestionToRemind($exeId); |
||
389 | break; |
||
390 | default: |
||
391 | $objExercise->editQuestionToRemind( |
||
392 | $exeId, |
||
393 | $_REQUEST['question_id'], |
||
394 | $_REQUEST['action'] |
||
395 | ); |
||
396 | break; |
||
397 | } |
||
398 | |||
399 | echo 1; |
||
400 | exit; |
||
401 | |||
402 | break; |
||
403 | case 'check_answers': |
||
404 | if (false === api_is_allowed_to_session_edit()) { |
||
405 | echo 'error'; |
||
406 | exit; |
||
407 | } |
||
408 | |||
409 | /** @var Exercise $objExercise */ |
||
410 | $objExercise = Session::read('objExercise'); |
||
411 | $questionList = Session::read('questionList'); |
||
412 | $exeId = Session::read('exe_id'); |
||
413 | |||
414 | // If exercise or question is not set then exit. |
||
415 | if (empty($questionList) || empty($objExercise)) { |
||
416 | echo 'error'; |
||
417 | exit; |
||
418 | } |
||
419 | |||
420 | $statInfo = $objExercise->get_stat_track_exercise_info_by_exe_id($exeId); |
||
421 | |||
422 | echo Display::page_subheader(get_lang('VerificationOfAnsweredQuestions')); |
||
423 | echo $objExercise->getReminderTable($questionList, $statInfo, true); |
||
424 | break; |
||
425 | case 'save_question_description': |
||
426 | if (!api_get_configuration_value('allow_quick_question_description_popup')) { |
||
427 | exit; |
||
428 | } |
||
429 | if (!api_is_allowed_to_edit(null, true)) { |
||
430 | exit; |
||
431 | } |
||
432 | |||
433 | /** @var \Exercise $objExercise */ |
||
434 | $objExercise = Session::read('objExercise'); |
||
435 | if (empty($objExercise)) { |
||
436 | exit; |
||
437 | } |
||
438 | |||
439 | $questionId = isset($_REQUEST['question_id']) ? (int) $_REQUEST['question_id'] : null; |
||
440 | $image = isset($_REQUEST['image']) ? $_REQUEST['image'] : ''; |
||
441 | |||
442 | $questionList = $objExercise->getQuestionList(); |
||
443 | |||
444 | if (!in_array($questionId, $questionList)) { |
||
445 | echo '0'; |
||
446 | exit; |
||
447 | } |
||
448 | |||
449 | $em = Database::getManager(); |
||
450 | $repo = $em->getRepository(CQuizQuestion::class); |
||
451 | /** @var CQuizQuestion $question */ |
||
452 | $question = $repo->find($questionId); |
||
453 | if (null !== $question) { |
||
454 | $question->setDescription('<img src="'.$image.'" />'); |
||
455 | $em->persist($question); |
||
456 | $em->flush(); |
||
457 | echo 1; |
||
458 | exit; |
||
459 | } |
||
460 | echo 0; |
||
461 | exit; |
||
462 | break; |
||
463 | case 'save_exercise_by_now': |
||
464 | header('Content-Type: application/json'); |
||
465 | |||
466 | $course_info = api_get_course_info_by_id($course_id); |
||
467 | |||
468 | if (empty($course_info)) { |
||
469 | echo json_encode(['error' => true]); |
||
470 | exit; |
||
471 | } |
||
472 | |||
473 | $course_id = $course_info['real_id']; |
||
474 | |||
475 | // Use have permissions to edit exercises results now? |
||
476 | if (false === api_is_allowed_to_session_edit()) { |
||
477 | echo json_encode(['error' => true]); |
||
478 | if ($debug) { |
||
479 | error_log( |
||
480 | 'Exercises attempt '.$exeId.': Failed saving question(s) in course/session '. |
||
481 | $course_id.'/'.$session_id. |
||
482 | ': The user ('.api_get_user_id().') does not have the permission to access this session now' |
||
483 | ); |
||
484 | } |
||
485 | exit; |
||
486 | } |
||
487 | |||
488 | // "all" or "simple" strings means that there's one or all questions exercise type |
||
489 | $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null; |
||
490 | |||
491 | // Questions choices. |
||
492 | $choice = isset($_REQUEST['choice']) ? $_REQUEST['choice'] : []; |
||
493 | |||
494 | // certainty degree choice |
||
495 | $choiceDegreeCertainty = isset($_REQUEST['choiceDegreeCertainty']) ? $_REQUEST['choiceDegreeCertainty'] : []; |
||
496 | |||
497 | // Hot spot coordinates from all questions. |
||
498 | $hot_spot_coordinates = isset($_REQUEST['hotspot']) ? $_REQUEST['hotspot'] : []; |
||
499 | |||
500 | // the filenames in upload answer type |
||
501 | $uploadAnswerFileNames = isset($_REQUEST['uploadChoice']) ? $_REQUEST['uploadChoice'] : []; |
||
502 | |||
503 | // There is a reminder? |
||
504 | $remind_list = isset($_REQUEST['remind_list']) && !empty($_REQUEST['remind_list']) |
||
505 | ? array_keys($_REQUEST['remind_list']) : []; |
||
506 | |||
507 | // Needed in manage_answer. |
||
508 | $learnpath_id = isset($_REQUEST['learnpath_id']) ? (int) $_REQUEST['learnpath_id'] : 0; |
||
509 | $learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? (int) $_REQUEST['learnpath_item_id'] : 0; |
||
510 | |||
511 | if ($debug) { |
||
512 | error_log("exe_id = $exeId"); |
||
513 | error_log("type = $type"); |
||
514 | error_log("choice = ".print_r($choice, 1)." "); |
||
515 | error_log("hot_spot_coordinates = ".print_r($hot_spot_coordinates, 1)); |
||
516 | error_log("remind_list = ".print_r($remind_list, 1)); |
||
517 | error_log("uploadAnswerFileNames = ".print_r($uploadAnswerFileNames, 1)); |
||
518 | error_log("--------------------------------"); |
||
519 | } |
||
520 | |||
521 | /** @var Exercise $objExercise */ |
||
522 | $objExercise = Session::read('objExercise'); |
||
523 | |||
524 | // Question info. |
||
525 | $question_id = isset($_REQUEST['question_id']) ? (int) $_REQUEST['question_id'] : null; |
||
526 | $question_list = Session::read('questionList'); |
||
527 | |||
528 | // If exercise or question is not set then exit. |
||
529 | if (empty($question_list) || empty($objExercise)) { |
||
530 | echo json_encode(['error' => true]); |
||
531 | if ($debug) { |
||
532 | if (empty($question_list)) { |
||
533 | error_log("question_list is empty"); |
||
534 | } |
||
535 | if (empty($objExercise)) { |
||
536 | error_log("objExercise is empty"); |
||
537 | } |
||
538 | } |
||
539 | exit; |
||
540 | } |
||
541 | |||
542 | if (WhispeakAuthPlugin::questionRequireAuthentify($question_id)) { |
||
543 | if ($objExercise->type == ONE_PER_PAGE) { |
||
544 | echo json_encode(['type' => 'one_per_page']); |
||
545 | exit; |
||
546 | } |
||
547 | |||
548 | echo json_encode(['ok' => true]); |
||
549 | exit; |
||
550 | } else { |
||
551 | ChamiloSession::erase(WhispeakAuthPlugin::SESSION_QUIZ_QUESTION); |
||
552 | } |
||
553 | |||
554 | // Getting information of the current exercise. |
||
555 | $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exeId); |
||
556 | $exercise_id = $exercise_stat_info['exe_exo_id']; |
||
557 | $attemptList = []; |
||
558 | // First time here we create an attempt (getting the exe_id). |
||
559 | if (!empty($exercise_stat_info)) { |
||
560 | // We know the user we get the exe_id. |
||
561 | $exeId = $exercise_stat_info['exe_id']; |
||
562 | $total_score = $exercise_stat_info['exe_result']; |
||
563 | // Getting the list of attempts |
||
564 | $attemptList = Event::getAllExerciseEventByExeId($exeId); |
||
565 | } |
||
566 | |||
567 | // No exe id? Can't save answer. |
||
568 | if (empty($exeId)) { |
||
569 | // Fires an error. |
||
570 | echo json_encode(['error' => true]); |
||
571 | if ($debug) { |
||
572 | error_log('exe_id is empty'); |
||
573 | } |
||
574 | exit; |
||
575 | } |
||
576 | |||
577 | Session::write('exe_id', $exeId); |
||
578 | |||
579 | // Updating Reminder algorithm. |
||
580 | if ($objExercise->type == ONE_PER_PAGE) { |
||
581 | $bd_reminder_list = explode(',', $exercise_stat_info['questions_to_check']); |
||
582 | if (empty($remind_list)) { |
||
583 | $remind_list = $bd_reminder_list; |
||
584 | $new_list = []; |
||
585 | foreach ($bd_reminder_list as $item) { |
||
586 | if ($item != $question_id) { |
||
587 | $new_list[] = $item; |
||
588 | } |
||
589 | } |
||
590 | $remind_list = $new_list; |
||
591 | } else { |
||
592 | if (isset($remind_list[0])) { |
||
593 | if (!in_array($remind_list[0], $bd_reminder_list)) { |
||
594 | array_push($bd_reminder_list, $remind_list[0]); |
||
595 | } |
||
596 | $remind_list = $bd_reminder_list; |
||
597 | } |
||
598 | } |
||
599 | } |
||
600 | |||
601 | // Getting the total weight if the request is simple. |
||
602 | $total_weight = 0; |
||
603 | if ($type === 'simple') { |
||
604 | foreach ($question_list as $my_question_id) { |
||
605 | $objQuestionTmp = Question::read($my_question_id, $objExercise->course); |
||
606 | $total_weight += $objQuestionTmp->selectWeighting(); |
||
607 | } |
||
608 | } |
||
609 | unset($objQuestionTmp); |
||
610 | |||
611 | if ($debug) { |
||
612 | error_log('Starting questions loop in save_exercise_by_now'); |
||
613 | } |
||
614 | |||
615 | $now = time(); |
||
616 | if ('all' === $type) { |
||
617 | // Check we have at least one non-empty answer in the array |
||
618 | // provided by the user's click on the "Finish test" button. |
||
619 | $atLeastOneAnswer = false; |
||
620 | foreach ($question_list as $my_question_id) { |
||
621 | if (!empty($choice[$my_question_id])) { |
||
622 | $atLeastOneAnswer = true; |
||
623 | break; |
||
624 | } |
||
625 | } |
||
626 | |||
627 | if (!$atLeastOneAnswer) { |
||
628 | // Check if time is over. |
||
629 | if ($objExercise->expired_time != 0) { |
||
630 | $clockExpiredTime = ExerciseLib::get_session_time_control_key( |
||
631 | $objExercise->iid, |
||
632 | $learnpath_id, |
||
633 | $learnpath_item_id |
||
634 | ); |
||
635 | if (!empty($clockExpiredTime)) { |
||
636 | $timeLeft = api_strtotime($clockExpiredTime, 'UTC') - $now; |
||
637 | if ($timeLeft <= 0) { |
||
638 | // There's no time, but still no answers ... |
||
639 | echo json_encode(['ok' => true, 'savedAnswerMessage' => '']); |
||
640 | exit; |
||
641 | } |
||
642 | } |
||
643 | } |
||
644 | |||
645 | error_log( |
||
646 | 'In '.__FILE__.'::action save_exercise_by_now,'. |
||
647 | ' from user '.api_get_user_id(). |
||
648 | ' for track_e_exercises.exe_id = '.$exeId. |
||
649 | ', we received an empty set of answers.'. |
||
650 | 'Preventing submission to avoid overwriting w/ null.' |
||
651 | ); |
||
652 | echo json_encode(['error' => true]); |
||
653 | exit; |
||
654 | } |
||
655 | } |
||
656 | |||
657 | // Looping the question list from database (not from the user answer) |
||
658 | foreach ($question_list as $my_question_id) { |
||
659 | if ($type === 'simple' && $question_id != $my_question_id) { |
||
660 | continue; |
||
661 | } |
||
662 | $my_choice = isset($choice[$my_question_id]) ? $choice[$my_question_id] : null; |
||
663 | $objQuestionTmp = Question::read($my_question_id, $objExercise->course); |
||
664 | $myChoiceDegreeCertainty = null; |
||
665 | if ($objQuestionTmp->type === MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { |
||
666 | if (isset($choiceDegreeCertainty[$my_question_id])) { |
||
667 | $myChoiceDegreeCertainty = $choiceDegreeCertainty[$my_question_id]; |
||
668 | } |
||
669 | } |
||
670 | if ($objQuestionTmp->type === UPLOAD_ANSWER) { |
||
671 | $my_choice = ''; |
||
672 | if (!empty($uploadAnswerFileNames)) { |
||
673 | $my_choice = implode('|', $uploadAnswerFileNames[$my_question_id]); |
||
674 | } |
||
675 | } |
||
676 | // Getting free choice data. |
||
677 | if ('all' === $type && in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION])) { |
||
678 | $my_choice = isset($_REQUEST['free_choice'][$my_question_id]) && !empty($_REQUEST['free_choice'][$my_question_id]) |
||
679 | ? $_REQUEST['free_choice'][$my_question_id] |
||
680 | : null; |
||
681 | } |
||
682 | |||
683 | if ($type === 'all') { |
||
684 | // If saving the whole exercise (not only one question), |
||
685 | // record the sum of individual max scores (called |
||
686 | // "exe_weighting" in track_e_exercises) |
||
687 | $total_weight += $objQuestionTmp->selectWeighting(); |
||
688 | } |
||
689 | |||
690 | // This variable came from exercise_submit_modal.php. |
||
691 | $hotspot_delineation_result = null; |
||
692 | if (isset($_SESSION['hotspot_delineation_result']) && |
||
693 | isset($_SESSION['hotspot_delineation_result'][$objExercise->selectId()]) |
||
694 | ) { |
||
695 | $hotspot_delineation_result = $_SESSION['hotspot_delineation_result'][$objExercise->selectId()][$my_question_id]; |
||
696 | } |
||
697 | |||
698 | if ('simple' === $type) { |
||
699 | // Getting old attempt in order to decrease the total score. |
||
700 | $old_result = $objExercise->manage_answer( |
||
701 | $exeId, |
||
702 | $my_question_id, |
||
703 | null, |
||
704 | 'exercise_show', |
||
705 | [], |
||
706 | false, |
||
707 | true, |
||
708 | false, |
||
709 | $objExercise->selectPropagateNeg() |
||
710 | ); |
||
711 | // Removing old score. |
||
712 | $total_score = $total_score - $old_result['score']; |
||
713 | } |
||
714 | |||
715 | $questionDuration = 0; |
||
716 | if (api_get_configuration_value('allow_time_per_question')) { |
||
717 | $extraFieldValue = new ExtraFieldValue('question'); |
||
718 | $value = $extraFieldValue->get_values_by_handler_and_field_variable($objQuestionTmp->iid, 'time'); |
||
719 | if (!empty($value) && isset($value['value']) && !empty($value['value'])) { |
||
720 | $questionDuration = Event::getAttemptQuestionDuration($exeId, $objQuestionTmp->iid); |
||
721 | if (empty($questionDuration)) { |
||
722 | echo json_encode(['error' => true]); |
||
723 | if ($debug) { |
||
724 | error_log("Question duration = 0, in exeId: $exeId, question_id: $my_question_id"); |
||
725 | } |
||
726 | exit; |
||
727 | } |
||
728 | } |
||
729 | } |
||
730 | |||
731 | // Deleting old attempt. |
||
732 | if (isset($attemptList) && !empty($attemptList[$my_question_id])) { |
||
733 | if ($debug) { |
||
734 | error_log("delete_attempt exe_id : $exeId, my_question_id: $my_question_id"); |
||
735 | } |
||
736 | Event::delete_attempt( |
||
737 | $exeId, |
||
738 | api_get_user_id(), |
||
739 | $course_id, |
||
740 | $session_id, |
||
741 | $my_question_id |
||
742 | ); |
||
743 | if ($objQuestionTmp->type === HOT_SPOT) { |
||
744 | Event::delete_attempt_hotspot( |
||
745 | $exeId, |
||
746 | api_get_user_id(), |
||
747 | $course_id, |
||
748 | $session_id, |
||
749 | $my_question_id |
||
750 | ); |
||
751 | } |
||
752 | |||
753 | if (isset($attemptList[$my_question_id]) && |
||
754 | isset($attemptList[$my_question_id]['marks']) |
||
755 | ) { |
||
756 | $total_score -= $attemptList[$my_question_id]['marks']; |
||
757 | } |
||
758 | } |
||
759 | |||
760 | // We're inside *one* question. Go through each possible answer for this question |
||
761 | if ($objQuestionTmp->type === MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { |
||
762 | $myChoiceTmp = []; |
||
763 | $myChoiceTmp['choice'] = $my_choice; |
||
764 | $myChoiceTmp['choiceDegreeCertainty'] = $myChoiceDegreeCertainty; |
||
765 | $result = $objExercise->manage_answer( |
||
766 | $exeId, |
||
767 | $my_question_id, |
||
768 | $myChoiceTmp, |
||
769 | 'exercise_result', |
||
770 | $hot_spot_coordinates, |
||
771 | true, |
||
772 | false, |
||
773 | false, |
||
774 | $objExercise->selectPropagateNeg(), |
||
775 | $hotspot_delineation_result, |
||
776 | true, |
||
777 | false, |
||
778 | false, |
||
779 | $questionDuration |
||
780 | ); |
||
781 | } else { |
||
782 | $result = $objExercise->manage_answer( |
||
783 | $exeId, |
||
784 | $my_question_id, |
||
785 | $my_choice, |
||
786 | 'exercise_result', |
||
787 | $hot_spot_coordinates, |
||
788 | true, |
||
789 | false, |
||
790 | false, |
||
791 | $objExercise->selectPropagateNeg(), |
||
792 | $hotspot_delineation_result, |
||
793 | true, |
||
794 | false, |
||
795 | false, |
||
796 | $questionDuration |
||
797 | ); |
||
798 | } |
||
799 | |||
800 | // Adding the new score. |
||
801 | $total_score += $result['score']; |
||
802 | |||
803 | if ($debug) { |
||
804 | error_log("total_score: $total_score "); |
||
805 | error_log("total_weight: $total_weight "); |
||
806 | } |
||
807 | |||
808 | $duration = 0; |
||
809 | if ($type === 'all') { |
||
810 | $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exeId); |
||
811 | } |
||
812 | |||
813 | $key = ExerciseLib::get_time_control_key( |
||
814 | $exercise_id, |
||
815 | $exercise_stat_info['orig_lp_id'], |
||
816 | $exercise_stat_info['orig_lp_item_id'] |
||
817 | ); |
||
818 | |||
819 | $durationTime = Session::read('duration_time'); |
||
820 | if (isset($durationTime[$key]) && !empty($durationTime[$key])) { |
||
821 | if ($debug) { |
||
822 | error_log('Session time: '.$durationTime[$key]); |
||
823 | } |
||
824 | $duration = $now - $durationTime[$key]; |
||
825 | if (!empty($exercise_stat_info['exe_duration'])) { |
||
826 | $duration += $exercise_stat_info['exe_duration']; |
||
827 | } |
||
828 | $duration = (int) $duration; |
||
829 | } else { |
||
830 | if (!empty($exercise_stat_info['exe_duration'])) { |
||
831 | $duration = $exercise_stat_info['exe_duration']; |
||
832 | } |
||
833 | } |
||
834 | |||
835 | if ($debug) { |
||
836 | error_log('duration to save in DB:'.$duration); |
||
837 | } |
||
838 | Session::write('duration_time', [$key => $now]); |
||
839 | Event::updateEventExercise( |
||
840 | $exeId, |
||
841 | $objExercise->selectId(), |
||
842 | $total_score, |
||
843 | $total_weight, |
||
844 | $session_id, |
||
845 | $exercise_stat_info['orig_lp_id'], |
||
846 | $exercise_stat_info['orig_lp_item_id'], |
||
847 | $exercise_stat_info['orig_lp_item_view_id'], |
||
848 | $duration, |
||
849 | $question_list, |
||
850 | 'incomplete', |
||
851 | $remind_list |
||
852 | ); |
||
853 | |||
854 | if (api_get_configuration_value('allow_time_per_question')) { |
||
855 | $questionStart = Session::read('question_start', []); |
||
856 | if (!empty($questionStart)) { |
||
857 | if (isset($questionStart[$my_question_id])) { |
||
858 | unset($questionStart[$my_question_id]); |
||
859 | } |
||
860 | array_filter($questionStart); |
||
861 | Session::write('question_start', $questionStart); |
||
862 | } |
||
863 | } |
||
864 | |||
865 | HookQuizQuestionAnswered::create() |
||
866 | ->setEventData( |
||
867 | [ |
||
868 | 'exe_id' => (int) $exeId, |
||
869 | 'quiz' => [ |
||
870 | 'id' => (int) $objExercise->iid, |
||
871 | 'title' => $objExercise->selectTitle(true), |
||
872 | ], |
||
873 | 'question' => [ |
||
874 | 'id' => (int) $my_question_id, |
||
875 | 'weight' => (float) $result['weight'], |
||
876 | ], |
||
877 | ] |
||
878 | ) |
||
879 | ->notifyQuizQuestionAnswered(); |
||
880 | |||
881 | // Destruction of the Question object |
||
882 | unset($objQuestionTmp); |
||
883 | if ($debug) { |
||
884 | error_log("---------- end question ------------"); |
||
885 | } |
||
886 | } |
||
887 | if ($debug) { |
||
888 | error_log('Finished questions loop in save_exercise_by_now'); |
||
889 | } |
||
890 | |||
891 | $questionsCount = count(explode(',', $exercise_stat_info['data_tracking'])); |
||
892 | $savedAnswersCount = $objExercise->countUserAnswersSavedInExercise($exeId); |
||
893 | |||
894 | if ($savedAnswersCount !== $questionsCount) { |
||
895 | $savedQuestionsMessage = Display::span( |
||
896 | sprintf(get_lang('XAnswersSavedByUsersFromXTotal'), $savedAnswersCount, $questionsCount), |
||
897 | ['class' => 'text-warning'] |
||
898 | ); |
||
899 | } else { |
||
900 | $savedQuestionsMessage = Display::span( |
||
901 | sprintf(get_lang('XAnswersSavedByUsersFromXTotal'), $savedAnswersCount, $questionsCount), |
||
902 | ['class' => 'text-success'] |
||
903 | ); |
||
904 | } |
||
905 | |||
906 | if ($type === 'all') { |
||
907 | if ($debug) { |
||
908 | error_log("result: ok - all"); |
||
909 | error_log(" ------ end ajax call ------- "); |
||
910 | } |
||
911 | echo json_encode(['ok' => true, 'savedAnswerMessage' => $savedQuestionsMessage]); |
||
912 | exit; |
||
913 | } |
||
914 | |||
915 | if ($objExercise->type == ONE_PER_PAGE) { |
||
916 | if ($debug) { |
||
917 | error_log("result: one_per_page"); |
||
918 | error_log(" ------ end ajax call ------- "); |
||
919 | } |
||
920 | echo json_encode(['type' => 'one_per_page', 'savedAnswerMessage' => $savedQuestionsMessage]); |
||
921 | exit; |
||
922 | } |
||
923 | if ($debug) { |
||
924 | error_log("result: ok"); |
||
925 | error_log(" ------ end ajax call ------- "); |
||
926 | } |
||
927 | echo json_encode(['ok' => true, 'savedAnswerMessage' => $savedQuestionsMessage]); |
||
928 | break; |
||
929 | case 'show_question': |
||
930 | $isAllowedToEdit = api_is_allowed_to_edit(null, true, false, false); |
||
931 | |||
932 | if (!$isAllowedToEdit) { |
||
933 | api_not_allowed(true); |
||
934 | exit; |
||
935 | } |
||
936 | |||
937 | $questionId = isset($_GET['question']) ? (int) $_GET['question'] : 0; |
||
938 | $exerciseId = isset($_REQUEST['exercise']) ? (int) $_REQUEST['exercise'] : 0; |
||
939 | |||
940 | if (!$questionId || !$exerciseId) { |
||
941 | break; |
||
942 | } |
||
943 | |||
944 | $objExercise = new Exercise(); |
||
945 | $objExercise->read($exerciseId); |
||
946 | $objQuestion = Question::read($questionId); |
||
947 | $id = ''; |
||
948 | if (api_get_configuration_value('show_question_id')) { |
||
949 | $id = '<h4>#'.$objQuestion->course['code'].'-'.$objQuestion->iid.'</h4>'; |
||
950 | } |
||
951 | echo $id; |
||
952 | echo '<p class="lead">'.$objQuestion->get_question_type_name().'</p>'; |
||
953 | if ($objQuestion->type === FILL_IN_BLANKS) { |
||
954 | echo '<script> |
||
955 | $(function() { |
||
956 | $(".selectpicker").selectpicker({}); |
||
957 | }); |
||
958 | </script>'; |
||
959 | } |
||
960 | |||
961 | // Allows render MathJax elements in a ajax call |
||
962 | if (api_get_setting('include_asciimathml_script') === 'true') { |
||
963 | echo '<script> MathJax.Hub.Queue(["Typeset",MathJax.Hub]);</script>'; |
||
964 | } |
||
965 | |||
966 | ExerciseLib::showQuestion( |
||
967 | $objExercise, |
||
968 | $questionId, |
||
969 | false, |
||
970 | null, |
||
971 | null, |
||
972 | false, |
||
973 | true, |
||
974 | false, |
||
975 | true, |
||
976 | true |
||
977 | ); |
||
978 | break; |
||
979 | case 'get_quiz_embeddable': |
||
980 | $exercises = ExerciseLib::get_all_exercises_for_course_id( |
||
981 | api_get_course_info(), |
||
982 | api_get_session_id(), |
||
983 | api_get_course_int_id(), |
||
984 | false |
||
985 | ); |
||
986 | |||
987 | $exercises = array_filter( |
||
988 | $exercises, |
||
989 | function (array $exercise) { |
||
990 | return ExerciseLib::isQuizEmbeddable($exercise); |
||
991 | } |
||
992 | ); |
||
993 | |||
994 | $result = []; |
||
995 | |||
996 | $codePath = api_get_path(WEB_CODE_PATH); |
||
997 | |||
998 | foreach ($exercises as $exercise) { |
||
999 | $title = Security::remove_XSS(api_html_entity_decode($exercise['title'])); |
||
1000 | |||
1001 | $result[] = [ |
||
1002 | 'id' => $exercise['iid'], |
||
1003 | 'title' => strip_tags($title), |
||
1004 | ]; |
||
1005 | } |
||
1006 | |||
1007 | header('Content-Type: application/json'); |
||
1008 | echo json_encode($result); |
||
1009 | break; |
||
1010 | case 'browser_test': |
||
1011 | $quizCheckButtonEnabled = api_get_configuration_value('quiz_check_button_enable'); |
||
1012 | |||
1013 | if ($quizCheckButtonEnabled) { |
||
1014 | if (isset($_POST['sleep'])) { |
||
1015 | sleep(2); |
||
1016 | } |
||
1017 | |||
1018 | echo 'ok'; |
||
1019 | } |
||
1020 | |||
1021 | break; |
||
1022 | case 'quiz_confirm_saved_answers': |
||
1023 | if (false === api_get_configuration_value('quiz_confirm_saved_answers')) { |
||
1024 | break; |
||
1025 | } |
||
1026 | |||
1027 | $trackConfirmationId = isset($_POST['tc_id']) ? (int) $_POST['tc_id'] : 0; |
||
1028 | $cId = api_get_course_int_id(); |
||
1029 | $sessionId = api_get_session_id(); |
||
1030 | $userId = api_get_user_id(); |
||
1031 | $confirmed = !empty($_POST['quiz_confirm_saved_answers_check']); |
||
1032 | |||
1033 | $em = Database::getManager(); |
||
1034 | $repo = $em->getRepository('ChamiloCoreBundle:TrackEExerciseConfirmation'); |
||
1035 | |||
1036 | try { |
||
1037 | if (!$trackConfirmationId) { |
||
1038 | throw new Exception(get_lang('ErrorOccurred')); |
||
1039 | } |
||
1040 | |||
1041 | /** @var TrackEExerciseConfirmation $trackConfirmation */ |
||
1042 | $trackConfirmation = $repo->findOneBy( |
||
1043 | [ |
||
1044 | 'id' => $trackConfirmationId, |
||
1045 | 'userId' => $userId, |
||
1046 | 'courseId' => $cId, |
||
1047 | 'sessionId' => $sessionId, |
||
1048 | ], |
||
1049 | ['createdAt' => 'DESC'] |
||
1050 | ); |
||
1051 | |||
1052 | if (!$trackConfirmation) { |
||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
1053 | throw new Exception(get_lang('NotFound')); |
||
1054 | } |
||
1055 | |||
1056 | $trackConfirmation |
||
1057 | ->setConfirmed($confirmed) |
||
1058 | ->setUpdatedAt(api_get_utc_datetime(null, false, true)); |
||
1059 | |||
1060 | $em->persist($trackConfirmation); |
||
1061 | $em->flush(); |
||
1062 | |||
1063 | http_response_code(200); |
||
1064 | } catch (Exception $exception) { |
||
1065 | http_response_code(500); |
||
1066 | |||
1067 | echo Display::return_message($exception->getMessage(), 'error'); |
||
1068 | } |
||
1069 | |||
1070 | break; |
||
1071 | case 'sign_attempt': |
||
1072 | api_block_anonymous_users(); |
||
1073 | if ('true' !== api_get_plugin_setting('exercise_signature', 'tool_enable')) { |
||
1074 | exit; |
||
1075 | } |
||
1076 | |||
1077 | $file = isset($_REQUEST['file']) ? $_REQUEST['file'] : ''; |
||
1078 | if (empty($exeId) || empty($file)) { |
||
1079 | echo 0; |
||
1080 | exit; |
||
1081 | } |
||
1082 | |||
1083 | $file = str_replace(' ', '+', $file); |
||
1084 | $track = ExerciseLib::get_exercise_track_exercise_info($exeId); |
||
1085 | if ($track) { |
||
1086 | $result = ExerciseSignaturePlugin::saveSignature($currentUserId, $track, $file); |
||
1087 | if ($result) { |
||
1088 | echo 1; |
||
1089 | exit; |
||
1090 | } |
||
1091 | } |
||
1092 | echo 0; |
||
1093 | break; |
||
1094 | case 'upload_answer': |
||
1095 | api_block_anonymous_users(); |
||
1096 | if (!empty($_FILES)) { |
||
1097 | $currentDirectory = Security::remove_XSS($_REQUEST['curdirpath']); |
||
1098 | $userId = api_get_user_id(); |
||
1099 | |||
1100 | // Upload answer path is created inside user personal folder my_files/upload_answer/[exe_id]/[question_id] |
||
1101 | $syspath = UserManager::getUserPathById($userId, 'system').'my_files'.$currentDirectory; |
||
1102 | @mkdir($syspath, api_get_permissions_for_new_directories(), true); |
||
1103 | $webpath = UserManager::getUserPathById($userId, 'web').'my_files'.$currentDirectory; |
||
1104 | |||
1105 | $files = $_FILES['files']; |
||
1106 | $fileList = []; |
||
1107 | foreach ($files as $name => $array) { |
||
1108 | $counter = 0; |
||
1109 | foreach ($array as $data) { |
||
1110 | $fileList[$counter][$name] = $data; |
||
1111 | $counter++; |
||
1112 | } |
||
1113 | } |
||
1114 | $resultList = []; |
||
1115 | foreach ($fileList as $file) { |
||
1116 | $json = []; |
||
1117 | |||
1118 | $filename = api_replace_dangerous_char($file['name']); |
||
1119 | $filename = disable_dangerous_file($filename); |
||
1120 | |||
1121 | if (move_uploaded_file($file['tmp_name'], $syspath.$filename)) { |
||
1122 | $title = $filename; |
||
1123 | $url = $webpath.$filename; |
||
1124 | $json['name'] = api_htmlentities($title); |
||
1125 | $json['link'] = Display::url( |
||
1126 | api_htmlentities($title), |
||
1127 | api_htmlentities($url), |
||
1128 | ['target' => '_blank'] |
||
1129 | ); |
||
1130 | $json['url'] = $url; |
||
1131 | $json['size'] = format_file_size($file['size']); |
||
1132 | $json['type'] = api_htmlentities($file['type']); |
||
1133 | $json['result'] = Display::return_icon( |
||
1134 | 'accept.png', |
||
1135 | get_lang('Uploaded') |
||
1136 | ); |
||
1137 | } else { |
||
1138 | $json['name'] = isset($file['name']) ? $filename : get_lang('Unknown'); |
||
1139 | $json['url'] = ''; |
||
1140 | $json['error'] = get_lang('Error'); |
||
1141 | } |
||
1142 | $resultList[] = $json; |
||
1143 | } |
||
1144 | echo json_encode(['files' => $resultList]); |
||
1145 | exit; |
||
1146 | } |
||
1147 | break; |
||
1148 | default: |
||
1149 | echo ''; |
||
1150 | } |
||
1151 | exit; |
||
1152 |