exercice.php 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Exercise list: This script shows the list of exercises for administrators and students.
  5. * @package chamilo.exercise
  6. * @author Olivier Brouckaert, original author
  7. * @author Denes Nagy, HotPotatoes integration
  8. * @author Wolfgang Schneider, code/html cleanup
  9. * @author Julio Montoya <gugli100@gmail.com>, lots of cleanup + several improvements
  10. */
  11. /**
  12. * Code
  13. */
  14. // name of the language file that needs to be included
  15. $language_file = array('exercice','tracking');
  16. // including the global library
  17. require_once '../inc/global.inc.php';
  18. require_once '../gradebook/lib/be.inc.php';
  19. // Setting the tabs
  20. $this_section = SECTION_COURSES;
  21. $htmlHeadXtra[] = api_get_jquery_ui_js();
  22. // Access control
  23. api_protect_course_script(true);
  24. $show = (isset ($_GET['show']) && $_GET['show'] == 'result') ? 'result' : 'test'; // moved down to fix bug: http://www.dokeos.com/forum/viewtopic.php?p=18609#18609
  25. // including additional libraries
  26. require_once 'exercise.class.php';
  27. require_once 'exercise.lib.php';
  28. require_once 'question.class.php';
  29. require_once 'answer.class.php';
  30. require_once api_get_path(LIBRARY_PATH) . 'fileManage.lib.php';
  31. require_once api_get_path(LIBRARY_PATH) . 'fileUpload.lib.php';
  32. require_once 'hotpotatoes.lib.php';
  33. require_once api_get_path(LIBRARY_PATH) . 'document.lib.php';
  34. require_once api_get_path(LIBRARY_PATH) . 'mail.lib.inc.php';
  35. /* Constants and variables */
  36. $is_allowedToEdit = api_is_allowed_to_edit(null,true);
  37. $is_tutor = api_is_allowed_to_edit(true);
  38. $is_tutor_course = api_is_course_tutor();
  39. $tbl_course_rel_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  40. $TBL_USER = Database :: get_main_table(TABLE_MAIN_USER);
  41. $TBL_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
  42. $TBL_ITEM_PROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  43. $TBL_EXERCICE_ANSWER = Database :: get_course_table(TABLE_QUIZ_ANSWER);
  44. $TBL_EXERCICE_QUESTION = Database :: get_course_table(TABLE_QUIZ_TEST_QUESTION);
  45. $TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST);
  46. $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
  47. $TBL_TRACK_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
  48. $TBL_TRACK_HOTPOTATOES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
  49. $TBL_TRACK_ATTEMPT = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
  50. $TBL_TRACK_ATTEMPT_RECORDING= Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
  51. $TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
  52. $TBL_LP_ITEM = Database :: get_course_table(TABLE_LP_ITEM);
  53. $TBL_LP_VIEW = Database :: get_course_table(TABLE_LP_VIEW);
  54. // document path
  55. $documentPath = api_get_path(SYS_COURSE_PATH) . $_course['path'] . "/document";
  56. // picture path
  57. $picturePath = $documentPath . '/images';
  58. // audio path
  59. $audioPath = $documentPath . '/audio';
  60. // hotpotatoes
  61. $uploadPath = DIR_HOTPOTATOES; //defined in main_api
  62. $exercicePath = api_get_self();
  63. $exfile = explode('/', $exercicePath);
  64. $exfile = strtolower($exfile[sizeof($exfile) - 1]);
  65. $exercicePath = substr($exercicePath, 0, strpos($exercicePath, $exfile));
  66. $exercicePath = $exercicePath . "exercice.php";
  67. if ($show == 'result') {
  68. if (empty($_GET['exerciseId']) && empty($_GET['path']) ) {
  69. //header('Location: exercice.php?' . api_get_cidreq());
  70. }
  71. }
  72. // Clear the exercise session
  73. if (isset ($_SESSION['objExercise'])) {
  74. api_session_unregister('objExercise');
  75. }
  76. if (isset ($_SESSION['objQuestion'])) {
  77. api_session_unregister('objQuestion');
  78. }
  79. if (isset ($_SESSION['objAnswer'])) {
  80. api_session_unregister('objAnswer');
  81. }
  82. if (isset ($_SESSION['questionList'])) {
  83. api_session_unregister('questionList');
  84. }
  85. if (isset ($_SESSION['exerciseResult'])) {
  86. api_session_unregister('exerciseResult');
  87. }
  88. //General POST/GET/SESSION/COOKIES parameters recovery
  89. if (empty ($origin)) {
  90. $origin = Security::remove_XSS($_REQUEST['origin']);
  91. }
  92. if (empty ($choice)) {
  93. $choice = $_REQUEST['choice'];
  94. }
  95. if (empty ($hpchoice)) {
  96. $hpchoice = $_REQUEST['hpchoice'];
  97. }
  98. if (empty ($exerciseId)) {
  99. $exerciseId = intval($_REQUEST['exerciseId']);
  100. }
  101. if (empty ($file)) {
  102. $file = Database :: escape_string($_REQUEST['file']);
  103. }
  104. $learnpath_id = intval($_REQUEST['learnpath_id']);
  105. $learnpath_item_id = intval($_REQUEST['learnpath_item_id']);
  106. $page = intval($_REQUEST['page']);
  107. if ($page < 0) {
  108. $page = 1;
  109. }
  110. if ($origin == 'learnpath') {
  111. $show = 'result';
  112. }
  113. //Deleting an attempt
  114. if ($_GET['delete'] == 'delete' && ($is_allowedToEdit || api_is_coach()) && !empty ($_GET['did']) && $_GET['did'] == strval(intval($_GET['did']))) {
  115. $sql = 'DELETE FROM ' . Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES) . ' WHERE exe_id = ' . $_GET['did']; //_GET[did] filtered by entry condition
  116. Database::query($sql);
  117. $filter=Security::remove_XSS($_GET['filter']);
  118. header('Location: exercice.php?cidReq=' . Security::remove_XSS($_GET['cidReq']) . '&show=result&filter=' . $filter . '&exerciseId='.$exerciseId.'&filter_by_user='.$_GET['filter_by_user']);
  119. exit;
  120. }
  121. //Send student email @todo move this code in a class, library
  122. if ($show == 'result' && $_REQUEST['comments'] == 'update' && ($is_allowedToEdit || $is_tutor) && $_GET['exeid']== strval(intval($_GET['exeid']))) {
  123. $id = intval($_GET['exeid']); //filtered by post-condition
  124. $track_exercise_info = get_exercise_track_exercise_info($id);
  125. if (empty($track_exercise_info)) {
  126. api_not_allowed();
  127. }
  128. $test = $track_exercise_info['title'];
  129. $student_id = $track_exercise_info['exe_user_id'];
  130. $course_id = $track_exercise_info['exe_cours_id'];
  131. $session_id = $track_exercise_info['session_id'];
  132. $lp_id = $track_exercise_info['orig_lp_id'];
  133. $lp_item_id = $track_exercise_info['orig_lp_item_id'];
  134. $lp_item_view_id = $track_exercise_info['orig_lp_item_view_id'];
  135. // Teacher data
  136. $teacher_info = api_get_user_info(api_get_user_id());
  137. $user_info = api_get_user_info($student_id);
  138. $student_email = $user_info['mail'];
  139. $from = $teacher_info['mail'];
  140. $from_name = api_get_person_name($teacher_info['firstname'], $teacher_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
  141. $url = api_get_path(WEB_CODE_PATH) . 'exercice/exercice.php?' . api_get_cidreq() . '&id_session='.$session_id.'&show=result&exerciseId='.$exerciseId;
  142. $my_post_info = array();
  143. $post_content_id = array();
  144. $comments_exist = false;
  145. foreach ($_POST as $key_index=>$key_value) {
  146. $my_post_info = explode('_',$key_index);
  147. $post_content_id[]=$my_post_info[1];
  148. if ($my_post_info[0]=='comments') {
  149. $comments_exist=true;
  150. }
  151. }
  152. $loop_in_track=($comments_exist===true) ? (count($_POST)/2) : count($_POST);
  153. $array_content_id_exe=array();
  154. if ($comments_exist===true) {
  155. $array_content_id_exe = array_slice($post_content_id,$loop_in_track);
  156. } else {
  157. $array_content_id_exe = $post_content_id;
  158. }
  159. for ($i=0;$i<$loop_in_track;$i++) {
  160. $my_marks = Database::escape_string($_POST['marks_'.$array_content_id_exe[$i]]);
  161. $contain_comments = Database::escape_string($_POST['comments_'.$array_content_id_exe[$i]]);
  162. if (isset($contain_comments)) {
  163. $my_comments = Database::escape_string($_POST['comments_'.$array_content_id_exe[$i]]);
  164. } else {
  165. $my_comments = '';
  166. }
  167. $my_questionid=$array_content_id_exe[$i];
  168. $sql = "SELECT question from $TBL_QUESTIONS WHERE id = '$my_questionid'";
  169. $result =Database::query($sql);
  170. $ques_name = Database::result($result,0,"question");
  171. $query = "UPDATE $TBL_TRACK_ATTEMPT SET marks = '$my_marks',teacher_comment = '$my_comments' WHERE question_id = ".$my_questionid." AND exe_id=".$id;
  172. Database::query($query);
  173. //Saving results in the track recording table
  174. $recording_changes = 'INSERT INTO '.$TBL_TRACK_ATTEMPT_RECORDING.' (exe_id, question_id, marks, insert_date, author, teacher_comment) VALUES
  175. ('."'$id','".$my_questionid."','$my_marks','".api_get_utc_datetime()."','".api_get_user_id()."'".',"'.$my_comments.'")';
  176. Database::query($recording_changes);
  177. }
  178. $qry = 'SELECT DISTINCT question_id, marks FROM ' . $TBL_TRACK_ATTEMPT . ' WHERE exe_id = '.$id .' GROUP BY question_id';
  179. $res = Database::query($qry);
  180. $tot = 0;
  181. while ($row = Database :: fetch_array($res, 'ASSOC')) {
  182. $tot += $row['marks'];
  183. }
  184. $totquery = "UPDATE $TBL_TRACK_EXERCICES SET exe_result = '".floatval($tot)."' WHERE exe_id = ".$id;
  185. Database::query($totquery);
  186. //@todo move this somewhere else
  187. $subject = get_lang('ExamSheetVCC');
  188. $course_info = api_get_course_info();
  189. $message = '<p>'.get_lang('DearStudentEmailIntroduction') . '</p><p>'.get_lang('AttemptVCC');
  190. $message .= '<h3>'.get_lang('CourseName'). '</h3><p>'.Security::remove_XSS($course_info['name']).'';
  191. $message .= '<h3>'.get_lang('Exercise') . '</h3><p>'.Security::remove_XSS($test);
  192. //Only for exercises not in a LP
  193. if ($lp_id == 0) {
  194. $message .= '<p>'.get_lang('ClickLinkToViewComment') . ' <a href="#url#">#url#</a><br />';
  195. }
  196. $message .= '<p>'.get_lang('Regards') . ' </p>';
  197. $message .= $from_name;
  198. $message = str_replace("#test#", Security::remove_XSS($test), $message);
  199. $message = str_replace("#url#", $url, $message);
  200. @api_mail_html($student_email, $student_email, $subject, $message, $from_name, $from, array('charset'=>api_get_system_encoding()));
  201. //Updating LP score here
  202. if (in_array($origin, array ('tracking_course','user_course','correct_exercise_in_lp'))) {
  203. $sql_update_score = "UPDATE $TBL_LP_ITEM_VIEW SET score = '" . floatval($tot) . "' WHERE id = " .$lp_item_view_id;
  204. Database::query($sql_update_score);
  205. if ($origin == 'tracking_course') {
  206. //Redirect to the course detail in lp
  207. header('location: exercice.php?course=' . Security :: remove_XSS($_GET['course']));
  208. exit;
  209. } else {
  210. //Redirect to the reporting
  211. header('location: ../mySpace/myStudents.php?origin=' . $origin . '&student=' . $student_id . '&details=true&course=' . $course_id.'&session_id='.$session_id);
  212. exit;
  213. }
  214. }
  215. }
  216. if (!empty($_GET['gradebook']) && $_GET['gradebook']=='view' ) {
  217. $_SESSION['gradebook']=Security::remove_XSS($_GET['gradebook']);
  218. $gradebook= $_SESSION['gradebook'];
  219. } elseif (empty($_GET['gradebook'])) {
  220. unset($_SESSION['gradebook']);
  221. $gradebook= '';
  222. }
  223. if (!empty($gradebook) && $gradebook=='view') {
  224. $interbreadcrumb[] = array ('url' => '../gradebook/' . $_SESSION['gradebook_dest'],'name' => get_lang('ToolGradebook'));
  225. }
  226. if ($show != 'result') {
  227. $nameTools = get_lang('Exercices');
  228. } else {
  229. if ($is_allowedToEdit || $is_tutor) {
  230. $nameTools = get_lang('StudentScore');
  231. $interbreadcrumb[] = array("url" => "exercice.php?gradebook=$gradebook","name" => get_lang('Exercices'));
  232. $objExerciseTmp = new Exercise();
  233. if ($objExerciseTmp->read($exerciseId)) {
  234. $interbreadcrumb[] = array("url" => "admin.php?exerciseId=".$exerciseId, "name" => $objExerciseTmp->name);
  235. }
  236. } else {
  237. $nameTools = get_lang('YourScore');
  238. $interbreadcrumb[] = array ("url" => "exercice.php?gradebook=$gradebook","name" => get_lang('Exercices'));
  239. }
  240. }
  241. // need functions of statsutils lib to display previous exercices scores
  242. require_once api_get_path(LIBRARY_PATH) . 'statsUtils.lib.inc.php';
  243. if ($is_allowedToEdit && !empty ($choice) && $choice == 'exportqti2') {
  244. require_once 'export/qti2/qti2_export.php';
  245. $export = export_exercise($exerciseId, true);
  246. require_once api_get_path(LIBRARY_PATH) . 'pclzip/pclzip.lib.php';
  247. $archive_path = api_get_path(SYS_ARCHIVE_PATH);
  248. $temp_dir_short = api_get_unique_id();
  249. $temp_zip_dir = $archive_path . "/" . $temp_dir_short;
  250. if (!is_dir($temp_zip_dir))
  251. mkdir($temp_zip_dir, api_get_permissions_for_new_directories());
  252. $temp_zip_file = $temp_zip_dir . "/" . api_get_unique_id() . ".zip";
  253. $temp_xml_file = $temp_zip_dir . "/qti2export_" . $exerciseId . '.xml';
  254. file_put_contents($temp_xml_file, $export);
  255. $zip_folder = new PclZip($temp_zip_file);
  256. $zip_folder->add($temp_xml_file, PCLZIP_OPT_REMOVE_ALL_PATH);
  257. $name = 'qti2_export_' . $exerciseId . '.zip';
  258. //DocumentManager::string_send_for_download($export,true,'qti2export_'.$exerciseId.'.xml');
  259. DocumentManager :: file_send_for_download($temp_zip_file, true, $name);
  260. unlink($temp_zip_file);
  261. unlink($temp_xml_file);
  262. rmdir($temp_zip_dir);
  263. exit; //otherwise following clicks may become buggy
  264. }
  265. if (!empty ($_GET['extra_data'])) {
  266. switch ($_GET['extra_data']) {
  267. case 'on' :
  268. $_SESSION['export_user_fields'] = true;
  269. break;
  270. default :
  271. $_SESSION['export_user_fields'] = false;
  272. break;
  273. }
  274. }
  275. if (!empty($_GET['export_report']) && $_GET['export_report'] == '1') {
  276. if (api_is_platform_admin() || api_is_course_admin() || api_is_course_tutor() || api_is_course_coach()) {
  277. $user_id = null;
  278. if (empty($_SESSION['export_user_fields']))
  279. $_SESSION['export_user_fields'] = false;
  280. if (!$is_allowedToEdit and !$is_tutor) {
  281. $user_id = api_get_user_id();
  282. }
  283. require_once 'exercise_result.class.php';
  284. switch ($_GET['export_format']) {
  285. case 'xls' :
  286. $export = new ExerciseResult();
  287. $export->exportCompleteReportXLS($documentPath, $user_id, $_SESSION['export_user_fields'], $_GET['export_filter'], $_GET['exerciseId'], $_GET['hotpotato_name']);
  288. exit;
  289. break;
  290. case 'csv' :
  291. default :
  292. $export = new ExerciseResult();
  293. $export->exportCompleteReportCSV($documentPath, $user_id, $_SESSION['export_user_fields'], $_GET['export_filter'], $_GET['exerciseId'], $_GET['hotpotato_name']);
  294. exit;
  295. break;
  296. }
  297. } else {
  298. api_not_allowed(true);
  299. }
  300. }
  301. if ($origin != 'learnpath') {
  302. //so we are not in learnpath tool
  303. Display :: display_header($nameTools, get_lang('Exercise'));
  304. if (isset ($_GET['message'])) {
  305. if (in_array($_GET['message'], array ('ExerciseEdited'))) {
  306. Display :: display_confirmation_message(get_lang($_GET['message']));
  307. }
  308. }
  309. } else {
  310. echo '<link rel="stylesheet" type="text/css" href="' . api_get_path(WEB_CODE_PATH) . 'css/default.css"/>';
  311. }
  312. event_access_tool(TOOL_QUIZ);
  313. // Tool introduction
  314. Display :: display_introduction_section(TOOL_QUIZ);
  315. HotPotGCt($documentPath, 1, api_get_user_id() );
  316. // only for administrator
  317. if ($is_allowedToEdit) {
  318. if (!empty($choice)) {
  319. // construction of Exercise
  320. $objExerciseTmp = new Exercise();
  321. $check = Security::check_token('get');
  322. if ($objExerciseTmp->read($exerciseId)) {
  323. if ($check) {
  324. switch ($choice) {
  325. case 'delete' : // deletes an exercise
  326. $objExerciseTmp->delete();
  327. require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/gradebook_functions.inc.php';
  328. $link_id = is_resource_in_course_gradebook(api_get_course_id(), 1 , $exerciseId, api_get_session_id());
  329. if ($link_id !== false) {
  330. remove_resource_from_course_gradebook($link_id);
  331. }
  332. Display :: display_confirmation_message(get_lang('ExerciseDeleted'));
  333. break;
  334. case 'enable' : // enables an exercise
  335. $objExerciseTmp->enable();
  336. $objExerciseTmp->save();
  337. // "WHAT'S NEW" notification: update table item_property (previously last_tooledit)
  338. Display :: display_confirmation_message(get_lang('VisibilityChanged'));
  339. break;
  340. case 'disable' : // disables an exercise
  341. $objExerciseTmp->disable();
  342. $objExerciseTmp->save();
  343. Display :: display_confirmation_message(get_lang('VisibilityChanged'));
  344. break;
  345. case 'disable_results' : //disable the results for the learners
  346. $objExerciseTmp->disable_results();
  347. $objExerciseTmp->save();
  348. Display :: display_confirmation_message(get_lang('ResultsDisabled'));
  349. break;
  350. case 'enable_results' : //disable the results for the learners
  351. $objExerciseTmp->enable_results();
  352. $objExerciseTmp->save();
  353. Display :: display_confirmation_message(get_lang('ResultsEnabled'));
  354. break;
  355. case 'clean_results' : //clean student results
  356. $quantity_results_deleted= $objExerciseTmp->clean_results();
  357. Display :: display_confirmation_message(sprintf(get_lang('XResultsCleaned'),$quantity_results_deleted));
  358. break;
  359. case 'copy_exercise' : //copy an exercise
  360. $objExerciseTmp->copy_exercise();
  361. Display :: display_confirmation_message(get_lang('ExerciseCopied'));
  362. break;
  363. }
  364. }
  365. }
  366. // destruction of Exercise
  367. unset ($objExerciseTmp);
  368. Security::clear_token();
  369. }
  370. if (!empty($hpchoice)) {
  371. switch($hpchoice) {
  372. case 'delete' : // deletes an exercise
  373. $imgparams = array ();
  374. $imgcount = 0;
  375. GetImgParams($file, $documentPath, $imgparams, $imgcount);
  376. $fld = GetFolderName($file);
  377. for ($i = 0; $i < $imgcount; $i++) {
  378. my_delete($documentPath . $uploadPath . "/" . $fld . "/" . $imgparams[$i]);
  379. update_db_info("delete", $uploadPath . "/" . $fld . "/" . $imgparams[$i]);
  380. }
  381. if (my_delete($documentPath . $file)) {
  382. update_db_info("delete", $file);
  383. }
  384. my_delete($documentPath . $uploadPath . "/" . $fld . "/");
  385. break;
  386. case 'enable' : // enables an exercise
  387. $newVisibilityStatus = "1"; //"visible"
  388. $query = "SELECT id FROM $TBL_DOCUMENT WHERE path='" . Database :: escape_string($file) . "'";
  389. $res = Database::query($query);
  390. $row = Database :: fetch_array($res, 'ASSOC');
  391. api_item_property_update($_course, TOOL_DOCUMENT, $row['id'], 'visible', $_user['user_id']);
  392. //$dialogBox = get_lang('ViMod');
  393. break;
  394. case 'disable' : // disables an exercise
  395. $newVisibilityStatus = "0"; //"invisible"
  396. $query = "SELECT id FROM $TBL_DOCUMENT WHERE path='" . Database :: escape_string($file) . "'";
  397. $res = Database::query($query);
  398. $row = Database :: fetch_array($res, 'ASSOC');
  399. api_item_property_update($_course, TOOL_DOCUMENT, $row['id'], 'invisible', $_user['user_id']);
  400. break;
  401. default :
  402. break;
  403. }
  404. }
  405. }
  406. // Actions div bar
  407. if ($is_allowedToEdit) {
  408. echo '<div class="actions">';
  409. } elseif ($show == 'result') {
  410. echo '<div class="actions">';
  411. }
  412. // Selects $limit exercises at the same time
  413. // maximum number of exercises on a same page
  414. $limit = 50;
  415. // Display the next and previous link if needed
  416. $from = $page * $limit;
  417. HotPotGCt($documentPath, 1, api_get_user_id());
  418. //condition for the session
  419. $session_id = api_get_session_id();
  420. $condition_session = api_get_session_condition($session_id,true,true);
  421. if ($show == 'test') {
  422. // Only for administrators
  423. if ($is_allowedToEdit) {
  424. $total_sql = "SELECT count(id) as count FROM $TBL_EXERCICES WHERE active<>'-1' $condition_session ";
  425. $sql = "SELECT * FROM $TBL_EXERCICES WHERE active<>'-1' $condition_session ORDER BY title LIMIT ".$from."," .$limit;
  426. } else {
  427. // Only for students
  428. $total_sql = "SELECT count(id) as count FROM $TBL_EXERCICES WHERE active = '1' $condition_session ";
  429. $sql = "SELECT id, title, type, description, results_disabled, session_id, start_time, end_time, max_attempt FROM $TBL_EXERCICES
  430. WHERE active='1' $condition_session
  431. ORDER BY title LIMIT ".$from."," .$limit;
  432. }
  433. $result = Database::query($sql);
  434. $exercises_count = Database :: num_rows($result);
  435. $result_total = Database::query($total_sql);
  436. $total_exercises = 0;
  437. if (Database :: num_rows($result_total)) {
  438. $result_total = Database::fetch_array($result_total);
  439. $total_exercises = $result_total['count'];
  440. }
  441. //get HotPotatoes files (active and inactive)
  442. if ($is_allowedToEdit) {
  443. $sql = "SELECT * FROM $TBL_DOCUMENT WHERE path LIKE '" . Database :: escape_string($uploadPath) . "/%/%'";
  444. $res = Database::query($sql);
  445. $hp_count = Database :: num_rows($res);
  446. } else {
  447. $res = Database::query("SELECT * FROM $TBL_DOCUMENT d, $TBL_ITEM_PROPERTY ip
  448. WHERE d.id = ip.ref AND ip.tool = '" . TOOL_DOCUMENT . "'
  449. AND d.path LIKE '" . Database :: escape_string($uploadPath) . "/%/%'
  450. AND ip.visibility='1'");
  451. $hp_count = Database :: num_rows($res);
  452. }
  453. $total = $total_exercises + $hp_count;
  454. }
  455. if ($is_allowedToEdit && $origin != 'learnpath') {
  456. if ($show != 'result') {
  457. echo '<a href="exercise_admin.php?' . api_get_cidreq() . '">' . Display :: return_icon('new_exercice.png', get_lang('NewEx'),'','32').'</a>';
  458. echo '<a href="question_create.php?' . api_get_cidreq() . '">' . Display :: return_icon('new_question.png', get_lang('AddQ'),'','32').'</a>';
  459. echo '<a href="hotpotatoes.php?' . api_get_cidreq() . '">' . Display :: return_icon('import_hotpotatoes.png', get_lang('ImportHotPotatoesQuiz'),'','32').'</a>';
  460. // link to import qti2 ...
  461. echo '<a href="qti2.php?' . api_get_cidreq() . '">' . Display :: return_icon('import_qti2.png', get_lang('ImportQtiQuiz'),'','32') .'</a>';
  462. echo '<a href="upload_exercise.php?' . api_get_cidreq() . '">' . Display :: return_icon('import_excel.png', get_lang('ImportExcelQuiz'),'','32') .'</a>';
  463. }
  464. // the actions for the statistics
  465. if ($show == 'result') {
  466. // the form
  467. if (api_is_platform_admin() || api_is_course_admin() || api_is_course_tutor() || api_is_course_coach()) {
  468. if ($_SESSION['export_user_fields']) {
  469. $alt = get_lang('ExportWithUserFields');
  470. $extra_user_fields = '<input type="hidden" name="export_user_fields" value="export_user_fields">';
  471. } else {
  472. $alt = get_lang('ExportWithoutUserFields');
  473. $extra_user_fields = '<input type="hidden" name="export_user_fields" value="do_not_export_user_fields">';
  474. }
  475. echo '<a href="admin.php?exerciseId='.intval($_GET['exerciseId']).'">' . Display :: return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').'</a>';
  476. echo '<script type="text/javascript">
  477. $(document).ready(function() {
  478. $( "#dialog:ui-dialog" ).dialog( "destroy" );
  479. $( "#dialog-confirm" ).dialog({
  480. autoOpen: false,
  481. show: "blind",
  482. resizable: false,
  483. height:250,
  484. modal: true
  485. });
  486. $("#export_opener").click(function() {
  487. var targetUrl = $(this).attr("href");
  488. $( "#dialog-confirm" ).dialog({
  489. width:350,
  490. height:220,
  491. buttons: {
  492. "'.addslashes(get_lang('Download')).'": function() {
  493. var export_format = $("input[name=export_format]:checked").val();
  494. var extra_data = $("input[name=load_extra_data]:checked").val();
  495. location.href = targetUrl+"&export_format="+export_format+"&extra_data="+extra_data;
  496. $( this ).dialog( "close" );
  497. },
  498. }
  499. });
  500. $( "#dialog-confirm" ).dialog("open");
  501. return false;
  502. });
  503. });
  504. </script>';
  505. echo '<div id="dialog-confirm" title="'.get_lang("ConfirmYourChoice").'">';
  506. echo Display::tag('p', Display::input('radio', 'export_format', 'csv', array('checked'=>'1', 'id'=>'export_format_csv_label')). Display::tag('label', get_lang('ExportAsCSV'), array('for'=>'export_format_csv_label')));
  507. echo Display::tag('p', Display::input('radio', 'export_format', 'xls', array('id'=>'export_format_xls_label')). Display::tag('label', get_lang('ExportAsXLS'), array('for'=>'export_format_xls_label')));
  508. echo Display::tag('p', Display::input('checkbox', 'load_extra_data', '0',array('id'=>'load_extra_data_id')). Display::tag('label', get_lang('LoadExtraData'), array('for'=>'load_extra_data_id')));
  509. echo '</div>';
  510. if ($_GET['filter'] == '1' or !isset ($_GET['filter']) or $_GET['filter'] == 0 ) {
  511. $filter = 1;
  512. } else {
  513. $filter = 2;
  514. }
  515. echo '<a id="export_opener" href="'.api_get_self().'?export_report=1&show=result&export_filter='.$filter.'&hotpotato_name='.Security::remove_XSS($_GET['path']).'&exerciseId='.intval($_GET['exerciseId']).'" >'.
  516. Display::return_icon('save.png', get_lang('Export'),'',32).'</a>';
  517. }
  518. }
  519. } else {
  520. //Student view
  521. if ($show == 'result') {
  522. echo '<a href="' . api_add_url_param($_SERVER['REQUEST_URI'], 'show=test') . '">' . Display :: return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').'</a>';
  523. }
  524. }
  525. if ($show == 'result') {
  526. if (api_is_allowed_to_edit(null,true)) {
  527. if (!$_GET['filter']) {
  528. $filter_by_not_revised = true;
  529. $filter = 1;
  530. } else {
  531. $filter=Security::remove_XSS($_GET['filter']);
  532. }
  533. $filter = (int)$_GET['filter'];
  534. switch ($filter) {
  535. case 1 :
  536. $filter_by_not_revised = true;
  537. break;
  538. case 2 :
  539. $filter_by_revised = true;
  540. break;
  541. default :
  542. null;
  543. }
  544. if (!empty($_GET['exerciseId']) && empty($_GET['filter_by_user'])) {
  545. if ($_GET['filter'] == '1' or !isset ($_GET['filter']) or $_GET['filter'] == 0 ) {
  546. $view_result = '<a href="' . api_get_self() . '?cidReq=' . api_get_course_id() . '&show=result&filter=2&id_session='.intval($_GET['id_session']).'&exerciseId='.intval($_GET['exerciseId']).'&gradebook='.$gradebook.'" >'.Display :: return_icon('exercice_check.png', get_lang('ShowCorrectedOnly'),'','32').'</a>';
  547. } else {
  548. $view_result = '<a href="' .api_get_self() . '?cidReq=' . api_get_course_id() . '&show=result&filter=1&id_session='.intval($_GET['id_session']).'&exerciseId='.intval($_GET['exerciseId']).'&gradebook='.$gradebook.'" >'.Display :: return_icon('exercice_uncheck.png', get_lang('ShowUnCorrectedOnly'),'','32').'</a>';
  549. }
  550. echo $view_result;
  551. }
  552. }
  553. }
  554. if ($is_allowedToEdit) {
  555. echo '</div>'; // closing the actions div
  556. } elseif ($show == 'result') {
  557. echo '</div>'; // closing the actions div
  558. }
  559. if ($show == 'test') {
  560. if ($total > $limit) {
  561. echo '<div style="float:right;height:20px;">';
  562. //show pages navigation link for previous page
  563. if ($page) {
  564. echo "<a href=\"" . api_get_self() . "?" . api_get_cidreq() . "&amp;page=" . ($page -1) . "\">" . Display :: return_icon('action_prev.png', get_lang('PreviousPage'))."</a>";
  565. } elseif ($total_exercises + $hp_count > $limit) {
  566. echo Display :: return_icon('action_prev_na.png', get_lang('PreviousPage'));
  567. }
  568. //show pages navigation link for previous page
  569. if ($total_exercises > $from + $limit || $hp_count > $from + $limit ) {
  570. echo ' '."<a href=\"" . api_get_self() . "?" . api_get_cidreq() . "&amp;page=" . ($page +1) . "\">" .Display::return_icon('action_next.png', get_lang('NextPage')) . "</a>";
  571. } elseif ($page) {
  572. echo ' '.Display :: return_icon('action_next_na.png', get_lang('NextPage'));
  573. }
  574. echo '</div>';
  575. }
  576. }
  577. if ($show == 'test') {
  578. $i =1;
  579. $lis = '';
  580. $exercise_list = array();
  581. $online_icon = Display::return_icon('online.png', get_lang('Visible'),array('width'=>'12px'));
  582. $offline_icon = Display::return_icon('offline.png',get_lang('Invisible'),array('width'=>'12px'));
  583. while ($row = Database :: fetch_array($result,'ASSOC')) {
  584. $exercise_list[] = $row;
  585. }
  586. echo '<table class="data_table">';
  587. if (!empty($exercise_list)) {
  588. /* Listing exercises */
  589. if ($origin != 'learnpath') {
  590. //avoid sending empty parameters
  591. $myorigin = (empty ($origin) ? '' : '&origin=' . $origin);
  592. $mylpid = (empty ($learnpath_id) ? '' : '&learnpath_id=' . $learnpath_id);
  593. $mylpitemid = (empty ($learnpath_item_id) ? '' : '&learnpath_item_id=' . $learnpath_item_id);
  594. $token = Security::get_token();
  595. $i=1;
  596. if ($is_allowedToEdit) {
  597. $headers = array(array('name' => get_lang('ExerciseName')),
  598. array('name' => get_lang('QuantityQuestions'), 'params' => array('width'=>'80px')),
  599. array('name' => get_lang('Actions'), 'params' => array('width'=>'180px')));
  600. } else {
  601. $headers = array(array('name' => get_lang('ExerciseName')),
  602. array('name' => get_lang('Status')),
  603. array('name' => get_lang('Results')));
  604. }
  605. $header_list = '';
  606. foreach($headers as $header) {
  607. $params = isset($header['params'])? $header['params'] : null;
  608. $header_list .= Display::tag('th', $header['name'], $params);
  609. }
  610. echo Display::tag('tr', $header_list);
  611. $count = 0;
  612. if (!empty($exercise_list))
  613. foreach ($exercise_list as $row) {
  614. //echo '<div id="tabs-'.$i.'">';
  615. $i++;
  616. //validacion when belongs to a session
  617. $session_img = api_get_session_image($row['session_id'], $_user['status']);
  618. $time_limits = false;
  619. if ($row['start_time'] != '0000-00-00 00:00:00' || $row['end_time'] != '0000-00-00 00:00:00') {
  620. $time_limits = true;
  621. }
  622. if ($time_limits) {
  623. // check if start time
  624. $start_time = false;
  625. if ($row['start_time'] != '0000-00-00 00:00:00') {
  626. $start_time = api_strtotime($row['start_time'],'UTC');
  627. }
  628. $end_time = false;
  629. if ($row['end_time'] != '0000-00-00 00:00:00') {
  630. $end_time = api_strtotime($row['end_time'],'UTC');
  631. }
  632. $now = time();
  633. $is_actived_time = false;
  634. //If both "clocks" are enable
  635. if ($start_time && $end_time) {
  636. if ($now > $start_time && $end_time > $now ) {
  637. $is_actived_time = true;
  638. }
  639. } else {
  640. //we check the start and end
  641. if ($start_time) {
  642. if ($now > $start_time) {
  643. $is_actived_time = true;
  644. }
  645. }
  646. if ($end_time) {
  647. if ($end_time > $now ) {
  648. $is_actived_time = true;
  649. }
  650. }
  651. }
  652. }
  653. //Blocking empty start times see BT#2800
  654. global $_custom;
  655. if (isset($_custom['exercises_hidden_when_no_start_date']) && $_custom['exercises_hidden_when_no_start_date']) {
  656. if (empty($row['start_time']) || $row['start_time'] == '0000-00-00 00:00:00') {
  657. $time_limits = true;
  658. $is_actived_time = false;
  659. }
  660. }
  661. // Teacher only
  662. if ($is_allowedToEdit) {
  663. $show_quiz_edition = true;
  664. $table_lp_item = Database::get_course_table(TABLE_LP_ITEM);
  665. $sql="SELECT max_score FROM $table_lp_item
  666. WHERE item_type = '".TOOL_QUIZ."' AND path ='".Database::escape_string($row['id'])."'";
  667. $result = Database::query($sql);
  668. if (Database::num_rows($result) > 0) {
  669. $show_quiz_edition = false;
  670. }
  671. $lp_blocked = '';
  672. if (!$show_quiz_edition) {
  673. $lp_blocked = Display::tag('font', '<i>'.get_lang('AddedToALP').'</i>', array('style'=>'color:grey'));
  674. }
  675. //Showing exercise title
  676. $row['title'] = text_filter(cut($row['title'], EXERCISE_MAX_NAME_SIZE));
  677. if ($session_id == $row['session_id']) {
  678. //Settings
  679. //echo Display::url(Display::return_icon('settings.png',get_lang('Edit'), array('width'=>'22px'))." ".get_lang('Edit'), 'exercise_admin.php?'.api_get_cidreq().'&modifyExercise=yes&exerciseId='.$row['id']);
  680. }
  681. if ($row['active'] == 0) {
  682. $title = Display::tag('font', $row['title'], array('style'=>'color:grey'));
  683. } else {
  684. $title = $row['title'];
  685. }
  686. $url = '<a href="overview.php?'.api_get_cidreq().$myorigin.$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'"><img src="../img/quiz.gif" /> '.$title.' </a>'.$lp_blocked;
  687. $item = Display::tag('td', $url.' '.$session_img);
  688. $exid = $row['id'];
  689. //count number exercice - teacher
  690. $sqlquery = "SELECT count(*) FROM $TBL_EXERCICE_QUESTION WHERE exercice_id = '" . $exid . "'";
  691. $sqlresult = Database::query($sqlquery);
  692. $rowi = Database :: result($sqlresult, 0);
  693. if ($session_id == $row['session_id']) {
  694. //Settings
  695. //$actions = Display::url(Display::return_icon('edit.png',get_lang('Edit'),'',22), 'exercise_admin.php?'.api_get_cidreq().'&modifyExercise=yes&exerciseId='.$row['id']);
  696. $actions = Display::url(Display::return_icon('edit.png',get_lang('Edit'),'',22), 'admin.php?'.api_get_cidreq().'&exerciseId='.$row['id']);
  697. $actions .='<a href="exercice.php?' . api_get_cidreq() . '&show=result&exerciseId='.$row['id'].'">' . Display :: return_icon('test_results.png', get_lang('Results'),'',22).'</a>';
  698. //Export
  699. $actions .= Display::url(Display::return_icon('cd.gif', get_lang('CopyExercise')), '', array('onclick'=>"javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToCopy'),ENT_QUOTES,$charset))." ".addslashes($row['title'])."?"."')) return false;",'href'=>'exercice.php?'.api_get_cidreq().'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$row['id']));
  700. //Clean exercise
  701. $actions .= Display::url(Display::return_icon('clean.png', get_lang('CleanStudentResults'),'',22),'', array('onclick'=>"javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDeleteResults'),ENT_QUOTES,$charset))." ".addslashes($row['title'])."?"."')) return false;",'href'=>'exercice.php?'.api_get_cidreq().'&choice=clean_results&sec_token='.$token.'&exerciseId='.$row['id']));
  702. //Visible / invisible
  703. if ($row['active']) {
  704. $actions .= Display::url(Display::return_icon('visible.png', get_lang('Deactivate'),'',22) , 'exercice.php?'.api_get_cidreq().'&choice=disable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']);
  705. } else { // else if not active
  706. $actions .= Display::url(Display::return_icon('invisible.png', get_lang('Activate'),'',22) , 'exercice.php?'.api_get_cidreq().'&choice=enable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']);
  707. }
  708. // Export qti ...
  709. $actions .= Display::url(Display::return_icon('export_qti2.png','IMS/QTI','','22'), 'exercice.php?choice=exportqti2&exerciseId='.$row['id']);
  710. } else { // not session resource
  711. $actions = Display::return_icon('edit_na.png', get_lang('ExerciseEditionNotAvailableInSession'));
  712. $actions .='<a href="exercice.php?' . api_get_cidreq() . '&show=result&exerciseId='.$row['id'].'">' . Display :: return_icon('test_results.png', get_lang('Results'),'',22).'</a>';
  713. $actions .= Display::url(Display::return_icon('cd.gif', get_lang('CopyExercise')), '', array('onclick'=>"javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToCopy'),ENT_QUOTES,$charset))." ".addslashes($row['title'])."?"."')) return false;",'href'=>'exercice.php?'.api_get_cidreq().'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$row['id']));
  714. }
  715. //Delete
  716. if ($session_id == $row['session_id']) {
  717. $actions .= Display::url(Display::return_icon('delete.png', get_lang('Delete'),'',22), '', array('onclick'=>"javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDelete'),ENT_QUOTES,$charset))." ".addslashes($row['title'])."?"."')) return false;",'href'=>'exercice.php?'.api_get_cidreq().'&choice=delete&sec_token='.$token.'&exerciseId='.$row['id']));
  718. }
  719. $random_label = '';
  720. if ($row['random'] > 0) {
  721. $random_label = ' ('.get_lang('Random').') ';
  722. $number_of_questions = $row['random'] . ' ' . api_strtolower(get_lang(($row['random'] > 1 ? 'Questions' : 'Question'))) .$random_label;
  723. } else {
  724. $number_of_questions = $rowi . ' ' . api_strtolower(get_lang(($rowi > 1 || $rowi == 0 ? 'Questions' : 'Question')));
  725. }
  726. //Attempts
  727. //$attempts = get_count_exam_results($row['id']).' '.get_lang('Attempts');
  728. //$item .= Display::tag('td',$attempts);
  729. $item .= Display::tag('td', $number_of_questions);
  730. } else {
  731. // --- Student only
  732. $row['title'] = cut($row['title'], EXERCISE_MAX_NAME_SIZE);
  733. // if time is actived show link to exercise
  734. if ($time_limits) {
  735. if ($is_actived_time) {
  736. $url = '<a href="overview.php?'.api_get_cidreq().$myorigin.$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'">'.$row['title'].'</a>';
  737. } else {
  738. $url = $row['title'];
  739. }
  740. } else {
  741. $url = '<a href="overview.php?'.api_get_cidreq().$myorigin.$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'">'.$row['title'].'</a>';
  742. }
  743. //Link of the exercise
  744. $item = Display::tag('td',$url.' '.$session_img);
  745. //count number exercise questions
  746. $sqlquery = "SELECT count(*) FROM $TBL_EXERCICE_QUESTION WHERE exercice_id = ".$row['id'];
  747. $sqlresult = Database::query($sqlquery);
  748. $rowi = Database::result($sqlresult, 0);
  749. if ($row['random'] > 0) {
  750. $row['random'] . ' ' . api_strtolower(get_lang(($row['random'] > 1 ? 'Questions' : 'Question')));
  751. } else {
  752. //show results student
  753. $rowi . ' ' . api_strtolower(get_lang(($rowi > 1 ? 'Questions' : 'Question')));
  754. }
  755. //This query might be improved later on by ordering by the new "tms" field rather than by exe_id
  756. //Don't remove this marker: note-query-exe-results
  757. $qry = "SELECT * FROM $TBL_TRACK_EXERCICES
  758. WHERE exe_exo_id = ".$row['id']." AND
  759. exe_user_id = ".api_get_user_id()." AND
  760. exe_cours_id = '".api_get_course_id()."' AND
  761. status <> 'incomplete' AND
  762. orig_lp_id = 0 AND
  763. orig_lp_item_id = 0 AND
  764. session_id = '" . api_get_session_id() . "'
  765. ORDER BY exe_id DESC";
  766. $qryres = Database::query($qry);
  767. $num = Database :: num_rows($qryres);
  768. //Hide the results
  769. $my_result_disabled = $row['results_disabled'];
  770. //Time limits are on
  771. if ($time_limits) {
  772. // Examn is ready to be taken
  773. if ($is_actived_time) {
  774. //Show results
  775. if ($my_result_disabled == 0 || $my_result_disabled == 2) {
  776. //More than one attempt
  777. if ($num > 0) {
  778. $row_track = Database :: fetch_array($qryres);
  779. $attempt_text = get_lang('LatestAttempt') . ' : ';
  780. $attempt_text .= show_score($row_track['exe_result'], $row_track['exe_weighting']);
  781. } else {
  782. //No attempts
  783. $attempt_text = get_lang('NotAttempted');
  784. }
  785. } else {
  786. $attempt_text = get_lang('CantShowResults');
  787. }
  788. } else {
  789. //Quiz not ready due to time limits
  790. if ($row['start_time'] != '0000-00-00 00:00:00' && $row['end_time'] != '0000-00-00 00:00:00') {
  791. $attempt_text = sprintf(get_lang('ExerciseWillBeActivatedFromXToY'), api_convert_and_format_date($row['start_time']), api_convert_and_format_date($row['end_time']));
  792. } else {
  793. //$attempt_text = get_lang('ExamNotAvailableAtThisTime');
  794. if ($row['start_time'] != '0000-00-00 00:00:00') {
  795. $attempt_text = sprintf(get_lang('ExerciseAvailableFromX'), api_convert_and_format_date($row['start_time']));
  796. }
  797. if ($row['end_time'] != '0000-00-00 00:00:00') {
  798. $attempt_text = sprintf(get_lang('ExerciseAvailableUntilX'), api_convert_and_format_date($row['end_time']));
  799. }
  800. }
  801. }
  802. } else {
  803. //Normal behaviour
  804. //Show results
  805. if ($my_result_disabled == 0 || $my_result_disabled == 2) {
  806. if ($num > 0) {
  807. $row_track = Database :: fetch_array($qryres);
  808. $attempt_text = get_lang('LatestAttempt') . ' : ';
  809. $attempt_text .= show_score($row_track['exe_result'], $row_track['exe_weighting']);
  810. } else {
  811. $attempt_text = get_lang('NotAttempted');
  812. }
  813. } else {
  814. $attempt_text = get_lang('CantShowResults');
  815. }
  816. }
  817. if (empty($num)) {
  818. $num = '';
  819. }
  820. $item .= Display::tag('td', $attempt_text);
  821. //See results
  822. $actions =' '.$num.' <a href="exercice.php?' . api_get_cidreq() . '&show=result&exerciseId='.$row['id'].'"> '.Display::return_icon('test_results.png', get_lang('Results'),'',22).' </a>';
  823. }
  824. $class = 'row_even';
  825. if ($count % 2) {
  826. $class = 'row_odd';
  827. }
  828. $item .= Display::tag('td', $actions);
  829. echo Display::tag('tr',$item, array('class'=>$class));
  830. $count++;
  831. } // end foreach()
  832. }
  833. }
  834. // end exercise list
  835. //Hotpotatoes results
  836. if ($is_allowedToEdit) {
  837. $sql = "SELECT d.path as path, d.comment as comment, ip.visibility as visibility
  838. FROM $TBL_DOCUMENT d, $TBL_ITEM_PROPERTY ip
  839. WHERE d.id = ip.ref AND ip.tool = '" . TOOL_DOCUMENT . "' AND (d.path LIKE '%htm%')
  840. AND d.path LIKE '" . Database :: escape_string($uploadPath) . "/%/%' LIMIT " .$from . "," .$limit; // only .htm or .html files listed
  841. } else {
  842. $sql = "SELECT d.path as path, d.comment as comment, ip.visibility as visibility
  843. FROM $TBL_DOCUMENT d, $TBL_ITEM_PROPERTY ip
  844. WHERE d.id = ip.ref AND ip.tool = '" . TOOL_DOCUMENT . "' AND (d.path LIKE '%htm%')
  845. AND d.path LIKE '" . Database :: escape_string($uploadPath) . "/%/%' AND ip.visibility='1' LIMIT " .$from . "," .$limit;
  846. }
  847. $result = Database::query($sql);
  848. while ($row = Database :: fetch_array($result, 'ASSOC')) {
  849. $attribute['path'][] = $row['path'];
  850. $attribute['visibility'][] = $row['visibility'];
  851. $attribute['comment'][] = $row['comment'];
  852. }
  853. $nbrActiveTests = 0;
  854. if (isset($attribute['path']) && is_array($attribute['path'])) {
  855. while (list($key, $path) = each($attribute['path'])) {
  856. $item = '';
  857. list ($a, $vis) = each($attribute['visibility']);
  858. if (strcmp($vis, "1") == 0) {
  859. $active = 1;
  860. } else {
  861. $active = 0;
  862. }
  863. $title = GetQuizName($path, $documentPath);
  864. if ($title == '') {
  865. $title = basename($path);
  866. }
  867. $class = 'row_even';
  868. if ($count % 2) {
  869. $class = 'row_odd';
  870. }
  871. // prof only
  872. if ($is_allowedToEdit) {
  873. $item = Display::tag('td','<img src="../img/hotpotatoes_s.png" alt="HotPotatoes" /> <a href="showinframes.php?file='.$path.'&cid='.api_get_course_id().'&uid='.api_get_user_id().'"'.(!$active?'class="invisible"':'').'>'.$title.'</a> ');
  874. $item .= Display::tag('td','-');
  875. $actions = Display::url(Display::return_icon('edit.png',get_lang('Edit'),'',22), 'adminhp.php?'.api_get_cidreq().'&hotpotatoesName='.$path);
  876. $actions .='<a href="exercice.php?' . api_get_cidreq() . '&show=result&path='.$path.'">' . Display :: return_icon('test_results.png', get_lang('Results'),'',22).'</a>';
  877. // if active
  878. if ($active) {
  879. $nbrActiveTests = $nbrActiveTests +1;
  880. $actions .= ' <a href="'.$exercicePath.'?'.api_get_cidreq().'&hpchoice=disable&amp;page='.$page.'&amp;file='.$path.'">'.Display::return_icon('visible.png', get_lang('Deactivate'),'',22).'</a>';
  881. } else { // else if not active
  882. $actions .=' <a href="'.$exercicePath.'?'.api_get_cidreq().'&hpchoice=enable&amp;page='.$page.'&amp;file='.$path.'">'.Display::return_icon('invisible.png', get_lang('Activate'),'',22).'</a>';
  883. }
  884. $actions .= '<a href="'.$exercicePath.'?'.api_get_cidreq().'&amp;hpchoice=delete&amp;file='.$path.'" onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('AreYouSureToDelete'),ENT_QUOTES,$charset).' '.$title."?").'\')) return false;">'.Display::return_icon('delete.png', get_lang('Delete'),'',22).'</a>';
  885. //$actions .='<img src="../img/lp_quiz_na.gif" border="0" title="'.get_lang('NotMarkActivity').'" alt="" />';
  886. $item .= Display::tag('td', $actions);
  887. echo Display::tag('tr',$item, array('class'=>$class));
  888. } else { // student only
  889. if ($active == 1) {
  890. $nbrActiveTests = $nbrActiveTests +1;
  891. $item .= Display::tag('td', '<a href="showinframes.php?'.api_get_cidreq().'&file='.$path.'&cid='.api_get_course_id().'&uid='.api_get_user_id().'"'.(!$active?'class="invisible"':'').'">'.$title.'</a>');
  892. $item .= Display::tag('td', '');
  893. //$item .= Display::tag('td', '');
  894. $actions ='<a href="exercice.php?' . api_get_cidreq() . '&show=result&path='.$path.'">' . Display :: return_icon('test_results.png', get_lang('Results'),'',22).'</a>';
  895. $item .= Display::tag('td', $actions);
  896. echo Display::tag('tr',$item, array('class'=>$class));
  897. }
  898. }
  899. $count ++;
  900. }
  901. }
  902. echo '</table>';
  903. Display :: display_footer();
  904. exit;
  905. }
  906. /* Exercise Results (uses tracking tool) */
  907. // if tracking is enabled
  908. if ($show == 'result') {
  909. $parameters=array('cidReq'=>Security::remove_XSS($_GET['cidReq']),'show'=>Security::remove_XSS($_GET['show']),'filter' => Security::remove_XSS($_GET['filter']),'gradebook' =>Security::remove_XSS($_GET['gradebook']));
  910. $exercise_id = intval($_GET['exerciseId']);
  911. if (!empty($exercise_id))
  912. $parameters['exerciseId'] = $exercise_id;
  913. if (!empty($_GET['path'])) {
  914. $parameters['path'] = Security::remove_XSS($_GET['path']);
  915. }
  916. $table = new SortableTable('quiz_results', 'get_count_exam_results', 'get_exam_results_data');
  917. $table->set_additional_parameters($parameters);
  918. if ($is_allowedToEdit || $is_tutor) {
  919. if (api_is_western_name_order()) {
  920. $table->set_header(0, get_lang('FirstName'));
  921. $table->set_header(1, get_lang('LastName'));
  922. } else {
  923. $table->set_header(0, get_lang('LastName'));
  924. $table->set_header(1, get_lang('FirstName'));
  925. }
  926. $table->set_header(2, get_lang('Exercice'));
  927. $table->set_header(3, get_lang('Duration'),false);
  928. $table->set_header(4, get_lang('Date'));
  929. $table->set_header(5, get_lang('Score'),false);
  930. $table->set_header(6, get_lang('CorrectTest'), false);
  931. } else {
  932. $table->set_header(0, get_lang('Exercice'));
  933. $table->set_header(1, get_lang('Duration'),false);
  934. $table->set_header(2, get_lang('Date'));
  935. $table->set_header(3, get_lang('Score'),false);
  936. $table->set_header(4, get_lang('Result'), false);
  937. }
  938. $table->display();
  939. }
  940. if ($origin != 'learnpath') { //so we are not in learnpath tool
  941. Display :: display_footer();
  942. }