exercise.ajax.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Responses to AJAX calls
  5. */
  6. require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.class.php';
  7. require_once api_get_path(SYS_CODE_PATH).'exercice/question.class.php';
  8. require_once api_get_path(SYS_CODE_PATH).'exercice/answer.class.php';
  9. use \ChamiloSession as Session;
  10. use Chamilo\CoreBundle\Framework\Container;
  11. api_protect_course_script(true);
  12. $action = $_REQUEST['a'];
  13. $course_id = api_get_course_int_id();
  14. if ($debug) {
  15. error_log("$action ajax call");
  16. }
  17. $session_id = isset($_REQUEST['session_id']) ? intval($_REQUEST['session_id']) : api_get_session_id();
  18. $course_code = isset($_REQUEST['cidReq']) ? $_REQUEST['cidReq'] : api_get_course_id();
  19. switch ($action) {
  20. case 'get_question':
  21. /** @var Exercise $objExercise */
  22. $objExercise = $_SESSION['objExercise'];
  23. $questionId = $_REQUEST['questionId'];
  24. $attemptList = isset($_REQUEST['attemptList']) ? $_REQUEST['attemptList'] : null;
  25. $remindList = isset($_REQUEST['remindList']) ? $_REQUEST['remindList'] : null;
  26. $i = $_REQUEST['i'];
  27. $current_question = $_REQUEST['current_question'];
  28. $questions_in_media = $_REQUEST['questions_in_media'];
  29. $last_question_in_media = $_REQUEST['last_question_in_media'];
  30. $realQuestionList = isset($_REQUEST['realQuestionList']) ? $_REQUEST['realQuestionList'] : null;
  31. $objExercise->renderQuestion(
  32. $questionId,
  33. $attemptList,
  34. $remindList,
  35. $i,
  36. $current_question,
  37. $questions_in_media,
  38. $last_question_in_media,
  39. $realQuestionList,
  40. false
  41. );
  42. break;
  43. case 'get_categories_by_media':
  44. $questionId = $_REQUEST['questionId'];
  45. $mediaId = $_REQUEST['mediaId'];
  46. $exerciseId = $_REQUEST['exerciseId'];
  47. $question = Question::read($questionId);
  48. if (empty($mediaId)) {
  49. echo 0;
  50. break;
  51. }
  52. $categoryId = $question->allQuestionWithMediaHaveTheSameCategory($exerciseId, $mediaId, null, null, true);
  53. if (!empty($categoryId)) {
  54. $category = new Testcategory($categoryId);
  55. echo json_encode(
  56. array(
  57. 'title' => $category->title,
  58. 'value' => $category->id
  59. )
  60. );
  61. } else {
  62. echo -1;
  63. }
  64. break;
  65. case 'exercise_category_exists':
  66. $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : 'simple';
  67. $category = new Testcategory(null, null, null, null, $type);
  68. $category->getCategory($_REQUEST['id']);
  69. if (empty($category->id)) {
  70. echo 0;
  71. } else {
  72. $courseId = api_get_course_int_id();
  73. if (isset($courseId)) {
  74. // Global
  75. if ($category->c_id == 0) {
  76. echo 1;
  77. exit;
  78. } else {
  79. // Local
  80. if ($category->c_id == $courseId) {
  81. echo 1;
  82. exit;
  83. }
  84. }
  85. } else {
  86. echo 0;
  87. exit;
  88. }
  89. }
  90. break;
  91. case 'search_category_parent':
  92. $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : 'simple';
  93. $filterByGlobal = isset($_REQUEST['filter_by_global']) ? $_REQUEST['filter_by_global'] : null;
  94. $cat = new Testcategory(null, null, null, null, $type);
  95. $items = $cat->get_categories_by_keyword($_REQUEST['tag']);
  96. $courseId = api_get_course_int_id();
  97. $em = Database::getManager();
  98. $repo = $em->getRepository('ChamiloCoreBundle:CQuizCategory');
  99. $json_items = array();
  100. if (!empty($items)) {
  101. foreach ($items as $item) {
  102. if ($item['c_id'] == 0) {
  103. if ($filterByGlobal) {
  104. $cat = $em->find('ChamiloCoreBundle:CQuizCategory', $item['iid']);
  105. $idList = array();
  106. if ($cat) {
  107. $path = $repo->getPath($cat);
  108. if (!empty($path)) {
  109. /** @var \Chamilo\Entity\CQuizCategory $cat */
  110. foreach ($path as $cat) {
  111. $idList[] = $cat->getIid();
  112. }
  113. }
  114. }
  115. if (isset($idList) && !empty($idList)) {
  116. if (!in_array($filterByGlobal, $idList)) {
  117. continue;
  118. }
  119. }
  120. }
  121. $item['title'] .= " [".get_lang('Global')."]";
  122. } else {
  123. if (isset($courseId)) {
  124. if ($item['c_id'] != $item['c_id']) {
  125. continue;
  126. }
  127. }
  128. }
  129. $json_items[] = array(
  130. 'key' => $item['iid'],
  131. 'value' => $item['title']
  132. );
  133. }
  134. }
  135. echo json_encode($json_items);
  136. break;
  137. case 'get_live_stats':
  138. if (!api_is_allowed_to_edit(null, true)) {
  139. break;
  140. }
  141. // 1. Setting variables needed by jqgrid
  142. $action = $_GET['a'];
  143. $exercise_id = intval($_GET['exercise_id']);
  144. $page = intval($_REQUEST['page']); //page
  145. $limit = intval($_REQUEST['rows']); //quantity of rows
  146. $sidx = $_REQUEST['sidx']; //index to filter
  147. $sord = $_REQUEST['sord']; //asc or desc
  148. if (!in_array($sord, array('asc','desc'))) {
  149. $sord = 'desc';
  150. }
  151. // get index row - i.e. user click to sort $sord = $_GET['sord'];
  152. // get the direction
  153. if (!$sidx) {
  154. $sidx = 1;
  155. }
  156. $track_exercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
  157. $user_table = Database::get_main_table(TABLE_MAIN_USER);
  158. $track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
  159. $minutes = intval($_REQUEST['minutes']);
  160. $now = time() - 60*$minutes; //1 hour
  161. $now = api_get_utc_datetime($now);
  162. $where_condition = " orig_lp_id = 0 AND exe_exo_id = $exercise_id AND start_date > '$now' ";
  163. $sql = "SELECT COUNT(DISTINCT exe_id) FROM $track_exercise WHERE $where_condition ";
  164. $result = Database::query($sql);
  165. $count = Database::fetch_row($result);
  166. $count = $count[0];
  167. //3. Calculating first, end, etc
  168. $total_pages = 0;
  169. if ($count > 0) {
  170. if (!empty($limit)) {
  171. $total_pages = ceil($count/$limit);
  172. }
  173. }
  174. if ($page > $total_pages) {
  175. $page = $total_pages;
  176. }
  177. $start = $limit * $page - $limit;
  178. if ($start < 0) {
  179. $start = 0;
  180. }
  181. $sql = "SELECT exe_id,
  182. exe_user_id,
  183. firstname,
  184. lastname,
  185. aa.status,
  186. start_date,
  187. exe_result,
  188. exe_weighting,
  189. exe_result/exe_weighting as score,
  190. exe_duration,
  191. questions_to_check,
  192. orig_lp_id
  193. FROM $user_table u
  194. INNER JOIN (
  195. SELECT t.exe_id, t.exe_user_id, status,
  196. start_date, exe_result, exe_weighting, exe_result/exe_weighting as score, exe_duration, questions_to_check, orig_lp_id
  197. FROM $track_exercise t LEFT JOIN $track_attempt a ON (a.exe_id = t.exe_id AND t.exe_user_id = a.user_id )
  198. WHERE t.status = 'incomplete' AND
  199. $where_condition
  200. GROUP BY exe_user_id
  201. ) as aa
  202. ON aa.exe_user_id = user_id
  203. ORDER BY $sidx $sord LIMIT $start, $limit";
  204. $result = Database::query($sql);
  205. $results = array();
  206. while ($row = Database::fetch_array($result, 'ASSOC')) {
  207. $results[] = $row;
  208. }
  209. $oExe = new exercise();
  210. $oExe->read($exercise_id);
  211. $response = new stdClass();
  212. $response->page = $page;
  213. $response->total = $total_pages;
  214. $response->records = $count;
  215. $i=0;
  216. if (!empty($results)) {
  217. foreach($results as $row) {
  218. $sql = "SELECT SUM(count_question_id) as count_question_id FROM (
  219. SELECT 1 as count_question_id FROM $track_attempt a
  220. WHERE user_id = {$row['exe_user_id']} and exe_id = {$row['exe_id']}
  221. GROUP by question_id
  222. ) as count_table";
  223. $result_count = Database::query($sql);
  224. $count_questions = Database::fetch_array($result_count,'ASSOC');
  225. $count_questions = $count_questions['count_question_id'];
  226. $row['count_questions'] = $count_questions;
  227. $response->rows[$i]['id'] = $row['exe_id'];
  228. $remaining = strtotime($row['start_date'])+($oExe->expired_time*60) - strtotime(api_get_utc_datetime(time()));
  229. $h = floor($remaining/3600);
  230. $m = floor(($remaining - ($h*3600))/60);
  231. $s = ($remaining - ($h*3600) - ($m*60));
  232. $array = array(
  233. $row['firstname'],
  234. $row['lastname'],
  235. api_format_date($row['start_date'], DATE_TIME_FORMAT_LONG).' ['.($h>0?$h.':':'').sprintf("%02d",$m).':'.sprintf("%02d",$s).']',
  236. $row['count_questions'],
  237. round($row['score']*100).'%'
  238. );
  239. $response->rows[$i]['cell'] = $array;
  240. $i++;
  241. }
  242. }
  243. echo json_encode($response);
  244. break;
  245. case 'update_exercise_list_order':
  246. if (api_is_allowed_to_edit(null, true)) {
  247. $new_list = $_REQUEST['exercise_list'];
  248. $table = Database::get_course_table(TABLE_QUIZ_ORDER);
  249. $counter = 1;
  250. //Drop all
  251. Database::query("DELETE FROM $table WHERE session_id = $session_id AND c_id = $course_id");
  252. //Insert all
  253. foreach ($new_list as $new_order_id) {
  254. Database::insert($table, array('exercise_order' => $counter, 'session_id' => $session_id, 'exercise_id' => intval($new_order_id), 'c_id' => $course_id));
  255. $counter++;
  256. }
  257. Display::display_confirmation_message(get_lang('Saved'));
  258. }
  259. break;
  260. case 'update_question_order':
  261. $course_info = api_get_course_info($course_code);
  262. $course_id = $course_info['real_id'];
  263. $exercise_id = isset($_REQUEST['exercise_id']) ? $_REQUEST['exercise_id'] : null;
  264. if (empty($exercise_id)) {
  265. return Display::display_error_message(get_lang('Error'));
  266. }
  267. if (api_is_allowed_to_edit(null, true)) {
  268. $new_question_list = $_POST['question_id_list'];
  269. $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  270. $counter = 1;
  271. foreach ($new_question_list as $new_order_id) {
  272. Database::update(
  273. $TBL_QUESTIONS,
  274. array('question_order' => $counter),
  275. array('question_id = ? AND c_id = ? AND exercice_id = ? '=> array(intval($new_order_id), $course_id, $exercise_id)));
  276. $counter++;
  277. }
  278. Display::display_confirmation_message(get_lang('Saved'));
  279. }
  280. break;
  281. case 'add_question_to_reminder':
  282. $objExercise = $_SESSION['objExercise'];
  283. if (empty($objExercise)) {
  284. echo 0;
  285. exit;
  286. } else {
  287. $objExercise->edit_question_to_remind($_REQUEST['exe_id'], $_REQUEST['question_id'], $_REQUEST['action']);
  288. }
  289. break;
  290. case 'save_exercise_by_now':
  291. $course_info = api_get_course_info($course_code);
  292. $course_id = $course_info['real_id'];
  293. //Use have permissions?
  294. if (api_is_allowed_to_session_edit()) {
  295. // "all" or "simple" strings means that there's one or all questions exercise type
  296. $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
  297. // Questions choices
  298. $choice = isset($_REQUEST['choice']) ? $_REQUEST['choice'] : null;
  299. // Hotspot coordinates from all questions
  300. $hot_spot_coordinates = isset($_REQUEST['hotspot']) ? $_REQUEST['hotspot'] : null;
  301. // There is a reminder?
  302. $remind_list = isset($_REQUEST['remind_list']) && !empty($_REQUEST['remind_list'])? array_keys($_REQUEST['remind_list']) : null;
  303. // Needed in manage_answer
  304. $learnpath_id = isset($_REQUEST['learnpath_id']) ? intval($_REQUEST['learnpath_id']) : 0;
  305. $learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? intval($_REQUEST['learnpath_item_id']) : 0;
  306. // Attempt id
  307. $exe_id = $_REQUEST['exe_id'];
  308. if ($debug) {
  309. error_log("exe_id = $exe_id ");
  310. error_log("type = $type ");
  311. error_log("choice = ".print_r($choice, 1)." ");
  312. error_log("hot_spot_coordinates = ".print_r($hot_spot_coordinates, 1));
  313. error_log("remind_list = ".print_r($remind_list, 1));
  314. }
  315. // Exercise information.
  316. /** @var \Exercise $objExercise */
  317. $objExercise = isset($_SESSION['objExercise']) ? $_SESSION['objExercise'] : null;
  318. // Question info.
  319. $question_id = isset($_REQUEST['question_id']) ? intval($_REQUEST['question_id']) : null;
  320. $question_list = Session::read('question_list_uncompressed');
  321. // If exercise or question is not set then exit.
  322. if (empty($question_list) || empty($objExercise)) {
  323. echo 'error';
  324. exit;
  325. }
  326. // Getting information of the current exercise.
  327. $exercise_stat_info = $objExercise->getStatTrackExerciseInfoByExeId($exe_id);
  328. $exercise_id = $exercise_stat_info['exe_exo_id'];
  329. $attempt_list = array();
  330. // First time here we create an attempt (getting the exe_id).
  331. if (empty($exercise_stat_info)) {
  332. } else {
  333. // We know the user we get the exe_id.
  334. $exe_id = $exercise_stat_info['exe_id'];
  335. $total_score = $exercise_stat_info['exe_result'];
  336. // Getting the list of attempts.
  337. $attempt_list = getAllExerciseEventByExeId($exe_id);
  338. }
  339. // Updating Reminder algorythme.
  340. if ($objExercise->type == ONE_PER_PAGE) {
  341. $bd_reminder_list = explode(',', $exercise_stat_info['questions_to_check']);
  342. // Fixing reminder order
  343. $fixedRemindList = array();
  344. if (!empty($bd_reminder_list)) {
  345. foreach ($question_list as $questionId) {
  346. if (in_array($questionId, $bd_reminder_list)) {
  347. $fixedRemindList[] = $questionId;
  348. }
  349. }
  350. }
  351. $bd_reminder_list = $fixedRemindList;
  352. if (empty($remind_list)) {
  353. $remind_list = $bd_reminder_list;
  354. $new_list = array();
  355. foreach ($bd_reminder_list as $item) {
  356. if ($item != $question_id) {
  357. $new_list[] = $item;
  358. }
  359. }
  360. $remind_list = $new_list;
  361. } else {
  362. if (isset($remind_list[0])) {
  363. if (!in_array($remind_list[0], $bd_reminder_list)) {
  364. array_push($bd_reminder_list, $remind_list[0]);
  365. }
  366. $remind_list = $bd_reminder_list;
  367. }
  368. }
  369. }
  370. // No exe id? Can't save answer!
  371. if (empty($exe_id)) {
  372. // Fires an error.
  373. echo 'error';
  374. exit;
  375. } else {
  376. $_SESSION['exe_id'] = $exe_id;
  377. }
  378. // Getting the total weight if the request is simple
  379. $total_weight = 0;
  380. if ($type == 'simple') {
  381. foreach ($question_list as $my_question_id) {
  382. $objQuestionTmp = Question::read($my_question_id, $course_id);
  383. $total_weight += $objQuestionTmp->selectWeighting();
  384. }
  385. }
  386. unset($objQuestionTmp);
  387. // Looping the question list
  388. if ($debug) {
  389. error_log("Looping question list".print_r($question_list, 1));
  390. error_log("Trying to save question: $question_id ");
  391. }
  392. foreach ($question_list as $my_question_id) {
  393. if ($type == 'simple' && $question_id != $my_question_id) {
  394. continue;
  395. }
  396. $my_choice = isset($choice[$my_question_id]) ? $choice[$my_question_id] : null;
  397. if ($debug) {
  398. error_log("Saving question_id = $my_question_id ");
  399. error_log("my_choice = ".print_r($my_choice, 1)."");
  400. }
  401. // Creates a temporary Question object
  402. $objQuestionTmp = Question::read($my_question_id, $course_id);
  403. if ($objExercise->type == ONE_PER_PAGE && $objQuestionTmp->type == UNIQUE_ANSWER) {
  404. if (in_array($my_question_id, $remind_list)) {
  405. if (empty($my_choice)) {
  406. echo 'answer_required';
  407. exit;
  408. }
  409. }
  410. }
  411. // Getting free choice data.
  412. if ($objQuestionTmp->type == FREE_ANSWER && $type == 'all') {
  413. $my_choice = isset($_REQUEST['free_choice'][$my_question_id]) && !empty($_REQUEST['free_choice'][$my_question_id])? $_REQUEST['free_choice'][$my_question_id]: null;
  414. }
  415. if ($type == 'all') {
  416. $total_weight += $objQuestionTmp->selectWeighting();
  417. }
  418. // This variable came from exercise_submit_modal.php
  419. $hotspot_delineation_result = null;
  420. if (isset($_SESSION['hotspot_delineation_result']) && isset($_SESSION['hotspot_delineation_result'][$objExercise->selectId()])) {
  421. $hotspot_delineation_result = $_SESSION['hotspot_delineation_result'][$objExercise->selectId()][$my_question_id];
  422. }
  423. if ($type == 'simple') {
  424. // Getting old attempt in order to decrees the total score.
  425. $old_result = $objExercise->manageAnswers(
  426. $exe_id,
  427. $my_question_id,
  428. null,
  429. 'exercise_show',
  430. array(),
  431. false,
  432. true,
  433. false
  434. );
  435. // Removing old score.
  436. $total_score = $total_score - $old_result['score'];
  437. if ($debug) {
  438. error_log("old score = ".$old_result['score']);
  439. error_log("total_score = ".$total_score."");
  440. }
  441. }
  442. // Deleting old attempt
  443. if (isset($attempt_list) && !empty($attempt_list[$my_question_id])) {
  444. if ($debug) {
  445. error_log("delete_attempt exe_id : $exe_id, my_question_id: $my_question_id");
  446. }
  447. delete_attempt($exe_id, api_get_user_id(), $course_id, $session_id, $my_question_id);
  448. if ($objQuestionTmp->type == HOT_SPOT) {
  449. delete_attempt_hotspot($exe_id, api_get_user_id(), $course_id, $my_question_id);
  450. }
  451. if (isset($attempt_list[$my_question_id]) && isset($attempt_list[$my_question_id]['marks'])) {
  452. $total_score -= $attempt_list[$my_question_id]['marks'];
  453. }
  454. }
  455. // We're inside *one* question. Go through each possible answer for this question
  456. $result = $objExercise->manageAnswers(
  457. $exe_id,
  458. $my_question_id,
  459. $my_choice,
  460. 'exercise_result',
  461. $hot_spot_coordinates,
  462. true,
  463. false,
  464. false,
  465. $hotspot_delineation_result
  466. );
  467. //Adding the new score
  468. $total_score += $result['score'];
  469. if ($debug) {
  470. error_log("total_score: $total_score ");
  471. error_log("total_weight: $total_weight ");
  472. }
  473. $duration = 0;
  474. $now = time();
  475. if ($type == 'all') {
  476. $exercise_stat_info = $objExercise->getStatTrackExerciseInfoByExeId($exe_id);
  477. }
  478. $key = ExerciseLib::get_time_control_key($exercise_id, $exercise_stat_info['orig_lp_id'], $exercise_stat_info['orig_lp_item_id']);
  479. /*$durationTime = array(
  480. 'duration_time' => array(
  481. $key => time()
  482. )
  483. );*/
  484. $durationTime = Session::read('duration_time');
  485. if (isset($durationTime[$key]) && !empty($durationTime[$key])) {
  486. $duration = $now - $durationTime[$key];
  487. if (!empty($exercise_stat_info['exe_duration'])) {
  488. $duration += $exercise_stat_info['exe_duration'];
  489. }
  490. $duration = intval($duration);
  491. } else {
  492. if (!empty($exercise_stat_info['exe_duration'])) {
  493. $duration = $exercise_stat_info['exe_duration'];
  494. }
  495. }
  496. $durationTime = array(
  497. $key => time()
  498. );
  499. Session::write('duration_time', $durationTime);
  500. // $_SESSION['duration_time'][$key] = time();
  501. update_event_exercise(
  502. $exe_id,
  503. $objExercise->selectId(),
  504. $total_score,
  505. $total_weight,
  506. $session_id,
  507. $exercise_stat_info['orig_lp_id'],
  508. $exercise_stat_info['orig_lp_item_id'],
  509. $exercise_stat_info['orig_lp_item_view_id'],
  510. $duration,
  511. 'incomplete',
  512. $remind_list
  513. );
  514. // Destruction of the Question object
  515. unset($objQuestionTmp);
  516. if ($debug) error_log(" -- end question -- ");
  517. }
  518. if ($debug) error_log(" ------ end ajax call ------- ");
  519. }
  520. if ($objExercise->type == ONE_PER_PAGE) {
  521. echo 'one_per_page';
  522. exit;
  523. }
  524. echo 'ok';
  525. break;
  526. case 'correct_exercise_result':
  527. $is_allowedToEdit = api_is_allowed_to_edit(null, true) || api_is_drh();
  528. $is_tutor = api_is_allowed_to_edit(true);
  529. //Send student email @todo move this code in a class, library
  530. if (isset($_POST['comments']) && $_POST['comments'] == 'update' && ($is_allowedToEdit || $is_tutor) && $_POST['exeid'] == strval(intval($_POST['exeid']))) {
  531. $exeId = intval($_POST['exeid']);
  532. $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
  533. $TBL_TRACK_EXERCICES = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
  534. $TBL_TRACK_ATTEMPT = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
  535. $TBL_TRACK_ATTEMPT_RECORDING = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
  536. $TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
  537. $track_exercise_info = ExerciseLib::get_exercise_track_exercise_info($exeId);
  538. if (empty($track_exercise_info)) {
  539. echo 0;
  540. }
  541. $test = $track_exercise_info['title'];
  542. $student_id = $track_exercise_info['exe_user_id'];
  543. $session_id = $track_exercise_info['session_id'];
  544. $lp_id = $track_exercise_info['orig_lp_id'];
  545. //$lp_item_id = $track_exercise_info['orig_lp_item_id'];
  546. $lp_item_view_id = $track_exercise_info['orig_lp_item_view_id'];
  547. $course_info = api_get_course_info();
  548. // Teacher data
  549. $teacher_info = api_get_user_info(api_get_user_id());
  550. $from_name = api_get_person_name(
  551. $teacher_info['firstname'],
  552. $teacher_info['lastname'],
  553. null,
  554. PERSON_NAME_EMAIL_ADDRESS
  555. );
  556. $url = api_get_path(WEB_CODE_PATH).'exercice/result.php?id='.$track_exercise_info['exe_id'].'&'.api_get_cidreq().'&show_headers=1&id_session='.$session_id;
  557. $commentIds = array();
  558. $marks = array();
  559. $comments = array();
  560. $result = array();
  561. $values = explode(',', $_POST['vals']);
  562. if (empty($values)) {
  563. echo 0;
  564. exit;
  565. }
  566. $countComments = count($commentIds);
  567. foreach ($values as $questionId) {
  568. $questionId = intval($questionId);
  569. $comment = isset($_POST['comments_'.$questionId]) ? $_POST['comments_'.$questionId] : null;
  570. $mark = isset($_POST['marks_'.$questionId]) ? $_POST['marks_'.$questionId] : null;
  571. $mark = Database::escape_string($mark);
  572. $comment = Database::escape_string($comment);
  573. $query = "UPDATE $TBL_TRACK_ATTEMPT SET marks = '$mark', teacher_comment = '$comment'
  574. WHERE question_id = ".$questionId." AND exe_id=".$exeId;
  575. Database::query($query);
  576. //Saving results in the track recording table
  577. $recording_changes = 'INSERT INTO '.$TBL_TRACK_ATTEMPT_RECORDING.' (exe_id, question_id, marks, insert_date, author, teacher_comment)
  578. VALUES ('."'$exeId','".$questionId."','$mark','".api_get_utc_datetime()."','".api_get_user_id()."'".',"'.$comment.'")';
  579. Database::query($recording_changes);
  580. }
  581. $qry = 'SELECT DISTINCT question_id, marks FROM '.$TBL_TRACK_ATTEMPT.' WHERE exe_id = '.$exeId.' GROUP BY question_id';
  582. $res = Database::query($qry);
  583. $tot = 0;
  584. while ($row = Database :: fetch_array($res, 'ASSOC')) {
  585. $tot += $row['marks'];
  586. }
  587. $sql = "UPDATE $TBL_TRACK_EXERCICES SET exe_result = '".floatval($tot)."' WHERE exe_id = ".$exeId;
  588. Database::query($sql);
  589. if (isset($_POST['send_notification'])) {
  590. //@todo move this somewhere else
  591. $subject = get_lang('ExamSheetVCC');
  592. $message = '<p>'.get_lang('DearStudentEmailIntroduction').'</p><p>'.get_lang('AttemptVCC');
  593. $message .= '<h3>'.get_lang('CourseName').'</h3><p>'.Security::remove_XSS($course_info['name']).'';
  594. $message .= '<h3>'.get_lang('Exercise').'</h3><p>'.Security::remove_XSS($test);
  595. //Only for exercises not in a LP
  596. if ($lp_id == 0) {
  597. $message .= '<p>'.get_lang('ClickLinkToViewComment').' <a href="#url#">#url#</a><br />';
  598. }
  599. $message .= '<p>'.get_lang('Regards').'</p>';
  600. $message .= $from_name;
  601. $message = str_replace("#test#", Security::remove_XSS($test), $message);
  602. $message = str_replace("#url#", $url, $message);
  603. MessageManager::send_message_simple($student_id, $subject, $message, api_get_user_id());
  604. }
  605. $origin = $_POST['origin'];
  606. // Updating LP score here
  607. if (isset($origin) && in_array($origin, array('tracking_course', 'user_course', 'correct_exercise_in_lp'))) {
  608. $sql_update_score = "UPDATE $TBL_LP_ITEM_VIEW SET score = '".floatval($tot)."' WHERE c_id = ".$course_id." AND id = ".$lp_item_view_id;
  609. Database::query($sql_update_score);
  610. }
  611. echo 1;
  612. exit;
  613. }
  614. echo 0;
  615. break;
  616. default:
  617. echo '';
  618. }
  619. exit;