exercice_submit.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. <?php
  2. /*
  3. DOKEOS - elearning and course management software
  4. For a full list of contributors, see documentation/credits.html
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. See "documentation/licence.html" more details.
  10. Contact:
  11. Dokeos
  12. Rue du Corbeau, 108
  13. B-1030 Brussels - Belgium
  14. info@dokeos.com
  15. */
  16. /**
  17. * Exercise submission
  18. * This script allows to run an exercise. According to the exercise type, questions
  19. * can be on an unique page, or one per page with a Next button.
  20. *
  21. * One exercise may contain different types of answers (unique or multiple selection,
  22. * matching, fill in blanks, free answer, hot-spot).
  23. *
  24. * Questions are selected randomly or not.
  25. *
  26. * When the user has answered all questions and clicks on the button "Ok",
  27. * it goes to exercise_result.php
  28. *
  29. * Notice : This script is also used to show a question before modifying it by
  30. * the administrator
  31. * @package dokeos.exercise
  32. * @author Olivier Brouckaert
  33. * @version $Id: exercice_submit.php 14930 2008-04-16 21:41:35Z juliomontoya $
  34. */
  35. include('exercise.class.php');
  36. include('question.class.php');
  37. include('answer.class.php');
  38. include('exercise.lib.php');
  39. // debug var. Set to 0 to hide all debug display. Set to 1 to display debug messages.
  40. $debug = 0;
  41. // answer types
  42. define('UNIQUE_ANSWER', 1);
  43. define('MULTIPLE_ANSWER', 2);
  44. define('FILL_IN_BLANKS', 3);
  45. define('MATCHING', 4);
  46. define('FREE_ANSWER', 5);
  47. define('HOT_SPOT', 6);
  48. define('HOT_SPOT_ORDER', 7);
  49. // name of the language file that needs to be included
  50. $language_file='exercice';
  51. include_once('../inc/global.inc.php');
  52. $this_section=SECTION_COURSES;
  53. /* ------------ ACCESS RIGHTS ------------ */
  54. // notice for unauthorized people.
  55. api_protect_course_script(true);
  56. include_once(api_get_path(LIBRARY_PATH).'text.lib.php');
  57. $is_allowedToEdit=api_is_allowed_to_edit();
  58. $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  59. $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
  60. $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
  61. $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER);
  62. // general parameters passed via POST/GET
  63. if ( empty ( $origin ) ) {
  64. $origin = $_REQUEST['origin'];
  65. }
  66. if ( empty ( $learnpath_id ) ) {
  67. $learnpath_id = Database::escape_string($_REQUEST['learnpath_id']);
  68. }
  69. if ( empty ( $learnpath_item_id ) ) {
  70. $learnpath_item_id = Database::escape_string($_REQUEST['learnpath_item_id']);
  71. }
  72. if ( empty ( $formSent ) ) {
  73. $formSent = $_REQUEST['formSent'];
  74. }
  75. if ( empty ( $exerciseResult ) ) {
  76. $exerciseResult = $_REQUEST['exerciseResult'];
  77. }
  78. if ( empty ( $exerciseResultCoordinates ) ) {
  79. $exerciseResultCoordinates = $_REQUEST['exerciseResultCoordinates'];
  80. }
  81. if ( empty ( $exerciseType ) ) {
  82. $exerciseType = $_REQUEST['exerciseType'];
  83. }
  84. if ( empty ( $exerciseId ) ) {
  85. $exerciseId = $_REQUEST['exerciseId'];
  86. }
  87. if ( empty ( $choice ) ) {
  88. $choice = $_REQUEST['choice'];
  89. }
  90. if ( empty ( $questionNum ) ) {
  91. $questionNum = Database::escape_string($_REQUEST['questionNum']);
  92. }
  93. if ( empty ( $nbrQuestions ) ) {
  94. $nbrQuestions = Database::escape_string($_REQUEST['nbrQuestions']);
  95. }
  96. if ( empty ($buttonCancel) ) {
  97. $buttonCancel = $_REQUEST['buttonCancel'];
  98. }
  99. // if the user has clicked on the "Cancel" button
  100. if($buttonCancel)
  101. {
  102. // returns to the exercise list
  103. header("Location: exercice.php?origin=$origin&learnpath_id=$learnpath_id&learnpath_item_id=$learnpath_item_id");
  104. exit();
  105. }
  106. if ($origin=='builder') {
  107. /*******************************/
  108. /* Clears the exercise session */
  109. /*******************************/
  110. if(isset($_SESSION['objExercise'])) { api_session_unregister('objExercise'); unset($objExercise); }
  111. if(isset($_SESSION['objQuestion'])) { api_session_unregister('objQuestion'); unset($objQuestion); }
  112. if(isset($_SESSION['objAnswer'])) { api_session_unregister('objAnswer'); unset($objAnswer); }
  113. if(isset($_SESSION['questionList'])) { api_session_unregister('questionList'); unset($questionList); }
  114. if(isset($_SESSION['exerciseResult'])) { api_session_unregister('exerciseResult'); unset($exerciseResult); }
  115. if(isset($_SESSION['exerciseResultCoordinates'])) { api_session_unregister('exerciseResultCoordinates'); unset($exerciseResultCoordinates); }
  116. }
  117. // if the user has submitted the form
  118. if($formSent)
  119. {
  120. if($debug>0){echo str_repeat('&nbsp;',0).'$formSent was set'."<br />\n";}
  121. // initializing
  122. if(!is_array($exerciseResult))
  123. {
  124. $exerciseResult=array();
  125. $exerciseResultCoordinates=array();
  126. }
  127. // if the user has answered at least one question
  128. if(is_array($choice))
  129. {
  130. if($debug>0){echo str_repeat('&nbsp;',0).'$choice is an array'."<br />\n";}
  131. if($exerciseType == 1)
  132. {
  133. // $exerciseResult receives the content of the form.
  134. // Each choice of the student is stored into the array $choice
  135. $exerciseResult=$choice;
  136. if (isset($_POST['hotspot']))
  137. {
  138. $exerciseResultCoordinates = $_POST['hotspot'];
  139. }
  140. }
  141. else
  142. {
  143. // gets the question ID from $choice. It is the key of the array
  144. list($key)=array_keys($choice);
  145. // if the user didn't already answer this question
  146. if(!isset($exerciseResult[$key]))
  147. {
  148. // stores the user answer into the array
  149. $exerciseResult[$key]=$choice[$key];
  150. if (isset($_POST['hotspot']))
  151. {
  152. $exerciseResultCoordinates[$key] = $_POST['hotspot'][$key];
  153. }
  154. }
  155. }
  156. if($debug>0){echo str_repeat('&nbsp;',0).'$choice is an array - end'."<br />\n";}
  157. }
  158. // the script "exercise_result.php" will take the variable $exerciseResult from the session
  159. api_session_register('exerciseResult');
  160. api_session_register('exerciseResultCoordinates');
  161. // if it is the last question (only for a sequential exercise)
  162. if($exerciseType == 1 || $questionNum >= $nbrQuestions)
  163. {
  164. if($debug>0){echo str_repeat('&nbsp;',0).'Redirecting to exercise_result.php - Remove debug option to let this happen'."<br />\n";}
  165. // goes to the script that will show the result of the exercise
  166. header("Location: exercise_result.php?origin=$origin&learnpath_id=$learnpath_id&learnpath_item_id=$learnpath_item_id");
  167. exit();
  168. }
  169. if($debug>0){echo str_repeat('&nbsp;',0).'$formSent was set - end'."<br />\n";}
  170. }
  171. // if the object is not in the session
  172. if(!isset($_SESSION['objExercise']) || $origin == 'learnpath')
  173. {
  174. if($debug>0){echo str_repeat('&nbsp;',0).'$_SESSION[objExercise] was unset'."<br />\n";}
  175. // construction of Exercise
  176. $objExercise=new Exercise();
  177. #$sql="SELECT title,description,sound,type,random,active FROM `$TBL_EXERCICES` WHERE id='$exerciseId'";
  178. // if the specified exercise doesn't exist or is disabled
  179. if(!$objExercise->read($exerciseId) || (!$objExercise->selectStatus() && !$is_allowedToEdit && ($origin != 'learnpath') ))
  180. {
  181. die(get_lang('ExerciseNotFound'));
  182. }
  183. // saves the object into the session
  184. api_session_register('objExercise');
  185. if($debug>0){echo str_repeat('&nbsp;',0).'$_SESSION[objExercise] was unset - set now - end'."<br />\n";}
  186. }
  187. if(!isset($objExcercise) && isset($_SESSION['objExercise'])){
  188. $objExercise = $_SESSION['objExercise'];
  189. }
  190. if(!is_object($objExercise))
  191. {
  192. header('Location: exercice.php');
  193. exit();
  194. }
  195. $exerciseTitle=$objExercise->selectTitle();
  196. $exerciseDescription=$objExercise->selectDescription();
  197. $exerciseDescription=stripslashes($exerciseDescription);
  198. $exerciseSound=$objExercise->selectSound();
  199. $randomQuestions=$objExercise->isRandom();
  200. $exerciseType=$objExercise->selectType();
  201. if(!isset($_SESSION['questionList']) || $origin == 'learnpath')
  202. {
  203. if($debug>0){echo str_repeat('&nbsp;',0).'$_SESSION[questionList] was unset'."<br />\n";}
  204. // selects the list of question ID
  205. $questionList = ($randomQuestions?$objExercise->selectRandomList():$objExercise->selectQuestionList());
  206. // saves the question list into the session
  207. api_session_register('questionList');
  208. if($debug>0){echo str_repeat('&nbsp;',0).'$_SESSION[questionList] was unset - set now - end'."<br />\n";}
  209. }
  210. if(!isset($objExcercise) && isset($_SESSION['objExercise'])){
  211. $questionList = $_SESSION['questionList'];
  212. }
  213. $nbrQuestions=sizeof($questionList);
  214. // if questionNum comes from POST and not from GET
  215. if(!$questionNum || $_POST['questionNum'])
  216. {
  217. // only used for sequential exercises (see $exerciseType)
  218. if(!$questionNum)
  219. {
  220. $questionNum=1;
  221. }
  222. else
  223. {
  224. $questionNum++;
  225. }
  226. }
  227. //$nameTools=get_lang('Exercice');
  228. $interbreadcrumb[]=array("url" => "exercice.php","name" => get_lang('Exercices'));
  229. $interbreadcrumb[]=array("url" => "#","name" => $exerciseTitle);
  230. if ($origin != 'learnpath') { //so we are not in learnpath tool
  231. $htmlHeadXtra[] = "<script type=\"text/javascript\" src=\"../plugin/hotspot/JavaScriptFlashGateway.js\"></script>
  232. <script src=\"../plugin/hotspot/hotspot.js\" type=\"text/javascript\"></script>
  233. <script language=\"JavaScript\" type=\"text/javascript\">
  234. <!--
  235. // -----------------------------------------------------------------------------
  236. // Globals
  237. // Major version of Flash required
  238. var requiredMajorVersion = 7;
  239. // Minor version of Flash required
  240. var requiredMinorVersion = 0;
  241. // Minor version of Flash required
  242. var requiredRevision = 0;
  243. // the version of javascript supported
  244. var jsVersion = 1.0;
  245. // -----------------------------------------------------------------------------
  246. // -->
  247. </script>
  248. <script language=\"VBScript\" type=\"text/vbscript\">
  249. <!-- // Visual basic helper required to detect Flash Player ActiveX control version information
  250. Function VBGetSwfVer(i)
  251. on error resume next
  252. Dim swControl, swVersion
  253. swVersion = 0
  254. set swControl = CreateObject(\"ShockwaveFlash.ShockwaveFlash.\" + CStr(i))
  255. if (IsObject(swControl)) then
  256. swVersion = swControl.GetVariable(\"\$version\")
  257. end if
  258. VBGetSwfVer = swVersion
  259. End Function
  260. // -->
  261. </script>
  262. <script language=\"JavaScript1.1\" type=\"text/javascript\">
  263. <!-- // Detect Client Browser type
  264. var isIE = (navigator.appVersion.indexOf(\"MSIE\") != -1) ? true : false;
  265. var isWin = (navigator.appVersion.toLowerCase().indexOf(\"win\") != -1) ? true : false;
  266. var isOpera = (navigator.userAgent.indexOf(\"Opera\") != -1) ? true : false;
  267. jsVersion = 1.1;
  268. // JavaScript helper required to detect Flash Player PlugIn version information
  269. function JSGetSwfVer(i){
  270. // NS/Opera version >= 3 check for Flash plugin in plugin array
  271. if (navigator.plugins != null && navigator.plugins.length > 0) {
  272. if (navigator.plugins[\"Shockwave Flash 2.0\"] || navigator.plugins[\"Shockwave Flash\"]) {
  273. var swVer2 = navigator.plugins[\"Shockwave Flash 2.0\"] ? \" 2.0\" : \"\";
  274. var flashDescription = navigator.plugins[\"Shockwave Flash\" + swVer2].description;
  275. descArray = flashDescription.split(\" \");
  276. tempArrayMajor = descArray[2].split(\".\");
  277. versionMajor = tempArrayMajor[0];
  278. versionMinor = tempArrayMajor[1];
  279. if ( descArray[3] != \"\" ) {
  280. tempArrayMinor = descArray[3].split(\"r\");
  281. } else {
  282. tempArrayMinor = descArray[4].split(\"r\");
  283. }
  284. versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
  285. flashVer = versionMajor + \".\" + versionMinor + \".\" + versionRevision;
  286. } else {
  287. flashVer = -1;
  288. }
  289. }
  290. // MSN/WebTV 2.6 supports Flash 4
  291. else if (navigator.userAgent.toLowerCase().indexOf(\"webtv/2.6\") != -1) flashVer = 4;
  292. // WebTV 2.5 supports Flash 3
  293. else if (navigator.userAgent.toLowerCase().indexOf(\"webtv/2.5\") != -1) flashVer = 3;
  294. // older WebTV supports Flash 2
  295. else if (navigator.userAgent.toLowerCase().indexOf(\"webtv\") != -1) flashVer = 2;
  296. // Can't detect in all other cases
  297. else {
  298. flashVer = -1;
  299. }
  300. return flashVer;
  301. }
  302. // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available
  303. function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision)
  304. {
  305. reqVer = parseFloat(reqMajorVer + \".\" + reqRevision);
  306. // loop backwards through the versions until we find the newest version
  307. for (i=25;i>0;i--) {
  308. if (isIE && isWin && !isOpera) {
  309. versionStr = VBGetSwfVer(i);
  310. } else {
  311. versionStr = JSGetSwfVer(i);
  312. }
  313. if (versionStr == -1 ) {
  314. return false;
  315. } else if (versionStr != 0) {
  316. if(isIE && isWin && !isOpera) {
  317. tempArray = versionStr.split(\" \");
  318. tempString = tempArray[1];
  319. versionArray = tempString .split(\",\");
  320. } else {
  321. versionArray = versionStr.split(\".\");
  322. }
  323. versionMajor = versionArray[0];
  324. versionMinor = versionArray[1];
  325. versionRevision = versionArray[2];
  326. versionString = versionMajor + \".\" + versionRevision; // 7.0r24 == 7.24
  327. versionNum = parseFloat(versionString);
  328. // is the major.revision >= requested major.revision AND the minor version >= requested minor
  329. if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) {
  330. return true;
  331. } else {
  332. return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false );
  333. }
  334. }
  335. }
  336. }
  337. // -->
  338. </script>";
  339. Display::display_header($nameTools,"Exercise");
  340. }
  341. else
  342. {
  343. if(empty($charset))
  344. {
  345. $charset = 'ISO-8859-15';
  346. }
  347. header('Content-Type: text/html; charset='. $charset);
  348. @$document_language = Database::get_language_isocode($language_interface);
  349. if(empty($document_language))
  350. {
  351. //if there was no valid iso-code, use the english one
  352. $document_language = 'en';
  353. }
  354. /*
  355. * HTML HEADER
  356. */
  357. ?>
  358. <!DOCTYPE html
  359. PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  360. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  361. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $document_language; ?>" lang="<?php echo $document_language; ?>">
  362. <head>
  363. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
  364. </head>
  365. <body>
  366. <link rel="stylesheet" type="text/css" href="<?php echo api_get_path(WEB_CODE_PATH).'css/'.api_get_setting('stylesheets').'/frames.css'; ?>" />
  367. <?php
  368. }
  369. $exerciseTitle=api_parse_tex($exerciseTitle);
  370. echo "<h3>".$exerciseTitle."</h3>";
  371. if(!empty($exerciseSound))
  372. {
  373. echo "<a href=\"../document/download.php?doc_url=%2Faudio%2F".$exerciseSound."\" target=\"_blank\">",
  374. "<img src=\"../img/sound.gif\" border=\"0\" align=\"absmiddle\" alt=",get_lang('Sound')."\" /></a>";
  375. }
  376. // Get number of hotspot questions for javascript validation
  377. $number_of_hotspot_questions = 0;
  378. $onsubmit = '';
  379. $i=0;
  380. foreach($questionList as $questionId)
  381. {
  382. $i++;
  383. $objQuestionTmp = Question :: read($questionId);
  384. // for sequential exercises
  385. if($exerciseType == 2)
  386. {
  387. // if it is not the right question, goes to the next loop iteration
  388. if($questionNum != $i)
  389. {
  390. continue;
  391. }
  392. else
  393. {
  394. if ($objQuestionTmp->selectType() == HOT_SPOT)
  395. {
  396. $number_of_hotspot_questions++;
  397. }
  398. break;
  399. }
  400. }
  401. else
  402. {
  403. if ($objQuestionTmp->selectType() == HOT_SPOT)
  404. {
  405. $number_of_hotspot_questions++;
  406. }
  407. }
  408. }
  409. if($number_of_hotspot_questions > 0)
  410. {
  411. $onsubmit = "onsubmit=\"return validateFlashVar('".$number_of_hotspot_questions."', '".get_lang('HotspotValidateError1')."', '".get_lang('HotspotValidateError2')."');\"";
  412. }
  413. $s="<p>$exerciseDescription</p>";
  414. if($origin == 'learnpath' && $exerciseType==2){
  415. $s2 = "&exerciseId=".$exerciseId;
  416. }
  417. $s.=" <form method='post' action='".api_get_self()."?autocomplete=off".$s2."' name='frm_exercise' $onsubmit>
  418. <input type='hidden' name='formSent' value='1' />
  419. <input type='hidden' name='exerciseType' value='".$exerciseType."' />
  420. <input type='hidden' name='questionNum' value='".$questionNum."' />
  421. <input type='hidden' name='nbrQuestions' value='".$nbrQuestions."' />
  422. <input type='hidden' name='origin' value='".$origin."' />
  423. <input type='hidden' name='learnpath_id' value='".$learnpath_id."' />
  424. <input type='hidden' name='learnpath_item_id' value='".$learnpath_item_id."' />
  425. <table width='100%' border='0' cellpadding='1' cellspacing='0'>
  426. <tr>
  427. <td>
  428. <table width='100%' cellpadding='3' cellspacing='0' border='0'>";
  429. echo $s;
  430. $i=0;
  431. foreach($questionList as $questionId)
  432. {
  433. $i++;
  434. // for sequential exercises
  435. if($exerciseType == 2)
  436. {
  437. // if it is not the right question, goes to the next loop iteration
  438. if($questionNum != $i)
  439. {
  440. continue;
  441. }
  442. else
  443. {
  444. // if the user has already answered this question
  445. if(isset($exerciseResult[$questionId]))
  446. {
  447. // construction of the Question object
  448. $objQuestionTmp = Question::read($questionId);
  449. $questionName=$objQuestionTmp->selectTitle();
  450. // destruction of the Question object
  451. unset($objQuestionTmp);
  452. echo '<tr><td>'.get_lang('AlreadyAnswered').' &quot;'.$questionName.'&quot;</td></tr>';
  453. break;
  454. }
  455. }
  456. }
  457. $s="<tr>
  458. <td width='3%' bgcolor='#e6e6e6'><img src=\"".api_get_path(WEB_IMG_PATH)."test.gif\" align=\"absmiddle\"></td>
  459. <td valign='middle' bgcolor='#e6e6e6'>
  460. ".get_lang('Question')." ";
  461. $s.=$i;
  462. if($exerciseType == 2) $s.=' / '.$nbrQuestions;
  463. $s.='</td></tr>';
  464. echo $s;
  465. // shows the question and its answers
  466. showQuestion($questionId, false, $origin);
  467. // for sequential exercises
  468. if($exerciseType == 2)
  469. {
  470. // quits the loop
  471. break;
  472. }
  473. } // end foreach()
  474. $s="</table>
  475. </td>
  476. </tr>
  477. <tr>
  478. <td><br/>
  479. <!-- <input type='submit' name='buttonCancel' value=".get_lang('Cancel')." />
  480. &nbsp;&nbsp; //-->
  481. <input type='submit' name='submit' value='";
  482. if ($exerciseType == 1 || $nbrQuestions == $questionNum)
  483. {
  484. $s.=get_lang('ValidateAnswer');
  485. }
  486. else
  487. {
  488. $s.=get_lang('Next').' &gt;';
  489. }
  490. //$s.='\'&gt;';
  491. $s.= '\' />';
  492. $s.="</td></tr></form></table>";
  493. $b=2;
  494. echo $s;
  495. if ($origin != 'learnpath') { //so we are not in learnpath tool
  496. Display::display_footer();
  497. }
  498. ?>