PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/www/question.php

http://wquiz.googlecode.com/
PHP | 287 lines | 151 code | 47 blank | 89 comment | 60 complexity | bc3ec9806f0a78fd2cf91c26ed76a8e6 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /** Copyright Information (GPL 3)
  3. Copyright Stewart Watkiss 2012
  4. This file is part of wQuiz.
  5. wQuiz is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. wQuiz is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with wQuiz. If not, see <http://www.gnu.org/licenses/>.
  15. **/
  16. // Enable debugging
  17. error_reporting(E_ALL);
  18. ini_set('display_errors', true);
  19. $debug = false;
  20. // Note that most of the error checking from form results just makes us switch to display
  21. // the question (or first / last question as appropriate) - this is not fed back to the user they just the question
  22. // look for $action = 'display' to see where we've switched back to default display
  23. require_once("includes/setup.php");
  24. require_once("includes/QuestionNavigation.php"); // used later for navigation buttons
  25. // action is a string based on button pressed - determines how we handle the post
  26. // default action is to show question
  27. $action = 'display';
  28. // message is used to provide feedback to the user
  29. // most cases we ignore errors, but for instance if a user does not enter a number in a number field we can notify the user of this when we go in display mode
  30. $message = '';
  31. // get the list of questions and current status
  32. $quiz_info = $quiz_session->getSessionInfo();
  33. if (!isset($quiz_info['status'])||!is_int($quiz_info['status']))
  34. {
  35. $err = Errors::getInstance();
  36. $err->errorEvent(WARNING_SESSION, "Session status is invalid");
  37. // kill session and send to index page
  38. $quiz_session->destroySession();
  39. // most likely session timed out or gone direct to question.php?
  40. // provide expired status
  41. header("Location: ".INDEX_FILE."?status=expired");
  42. exit (0);
  43. }
  44. // Check we have valid status - if already complete we go to the end page
  45. // otherwise if not active go back to start (no status message)
  46. if ($quiz_info['status'] == SESSION_STATUS_COMPLETE)
  47. {
  48. $err = Errors::getInstance();
  49. $err->errorEvent(WARNING_SESSION, "Session already complete");
  50. // Go to end / review page (leave session intact)
  51. header("Location: ".END_FILE);
  52. exit (0);
  53. }
  54. else if ($quiz_info['status'] != SESSION_STATUS_ACTIVE)
  55. {
  56. $err = Errors::getInstance();
  57. $err->errorEvent(WARNING_SESSION, "Session is not active - status ".$quiz_info['status']);
  58. // kill session and send to index page
  59. $quiz_session->destroySession();
  60. header("Location: ".INDEX_FILE);
  61. exit (0);
  62. }
  63. // Get the list of question numbers and current answers from session
  64. $questions_array = $quiz_session->getQuestions();
  65. // If we don't have questions then we error
  66. if (count($questions_array)<1)
  67. {
  68. $err = Errors::getInstance();
  69. $err->errorEvent(ERROR_SESSION, "Session does not have any questions defined");
  70. }
  71. else {$num_questions = count($questions_array);}
  72. $answers_array = $quiz_session->getAnswers();
  73. // class for action
  74. // we are using default from settings - could override here if required - will also need to pass with showNavigation
  75. $navigation = new QuestionNavigation(1, $num_questions);
  76. //submit buttons
  77. // Determine what action required based on submit
  78. if (isset($_POST['nav']))
  79. {
  80. // see if this is a valid action - gets action back
  81. $action = $navigation->getAction ($_POST['nav']);
  82. if ($action == 'invalid')
  83. {
  84. $err = Errors::getInstance();
  85. $err->errorEvent(WARNING_PARAMETER, "Action invalid - defaulting to display");
  86. $action = 'display';
  87. }
  88. }
  89. // get question number from the post
  90. // question number is from 1 upwards - not 0 as the session array does
  91. // Check that this is a number and that it is within the session questions - otherwise we default to 1st question
  92. // if we have to change the question number to default then we also change the action to default - for example should not be saving answer if answer was given to out-of-range question
  93. // note is_int does not work - so using is_numeric instead
  94. if (!isset($_POST['question']) || !is_numeric($_POST['question']) || $_POST['question'] < 1)
  95. {
  96. $question_num = 1;
  97. // set action to default as we didn't have a valid question number
  98. $err = Errors::getInstance();
  99. $err->errorEvent(INFO_PARAMETER, "No question number provided - using default display and question 1");
  100. $action == 'display';
  101. }
  102. elseif ($_POST['question'] > $num_questions)
  103. {
  104. $question_num = $num_questions;
  105. $err = Errors::getInstance();
  106. $err->errorEvent(WARNING_PARAMETER, "Parameter question number too high setting to max / display");
  107. // set action to default as we didn't have a valid question number
  108. $action == 'display';
  109. }
  110. else {$question_num = $_POST['question'];}
  111. // load this question - note -1 used to select array position (ie. question 1 = array 0)
  112. // if we are just doing a display then we can use this same instance for the display later - otherwise we will need a new instance for the new question
  113. $question_from = new Question($qdb->getQuestion($questions_array[$question_num-1]));
  114. // Save answer if changed
  115. $answer = '';
  116. // check for hidden field to show that this was from an existing question
  117. if ($action != 'display')
  118. {
  119. // no type - we didn't come from a question display
  120. if (!isset ($_POST['type']) || !$question_from->validateType($_POST['type']))
  121. {
  122. $err = Errors::getInstance();
  123. $err->errorEvent(WARNING_PARAMETER, "Parameter type does not match question type");
  124. $action = 'display';
  125. }
  126. // checkbox is handled differently for a checkbox as it can be multiple answers
  127. else if ($_POST['type'] == 'checkbox')
  128. {
  129. for ($i=0; $i<10; $i++)
  130. {
  131. if (isset ($_POST['answer-'.$i])) {$answer .= $i;}
  132. }
  133. // if none selected set back to default (-1)
  134. if ($answer == '') {$answer = -1;}
  135. }
  136. // handle default where answer is not set at all (eg. radio with nothing ticked)
  137. else if (!isset ($_POST['answer']) || $_POST['answer'] == '')
  138. {
  139. $answer = -1;
  140. }
  141. else // All others we just have one value from post which is $answers
  142. {
  143. if ($question_from->validateAnswer($_POST['answer']))
  144. {
  145. $answer = $_POST['answer'];
  146. // remove magic quotes if applied - so that the regular expression matching works correctly
  147. if (get_magic_quotes_gpc()) { $answer = stripslashes($answer); }
  148. }
  149. else
  150. {
  151. // set message as this may have been a genuine error (eg. seven instead of 7)
  152. $err = Errors::getInstance();
  153. $err->errorEvent(INFO_PARAMETER, "Answer provided is not a valid response for ". $question_from->getType());
  154. $message = 'Answer provided is not a valid response';
  155. $action = 'display';
  156. }
  157. }
  158. }
  159. // check that we haven't changed back to display due to invalid entry before we save
  160. if ($action != 'display')
  161. {
  162. $all_answers = $quiz_session->getAnswers();
  163. // check for exact match (checkbox 01 == 1 which is wrong)
  164. if ($all_answers[$question_num-1] !== $answer)
  165. {
  166. $all_answers[$question_num-1] = $answer;
  167. $quiz_session->setAnswers($all_answers);
  168. }
  169. // otherwise not changed so no need to save
  170. }
  171. // We have already saved so we can now move to the next requested page
  172. // what is next action based on which button pressed
  173. if ($debug) {print "Action is $action";}
  174. if ($action == 'first') {$question_num = 1;}
  175. else if ($action == 'previous') {$question_num--;}
  176. else if ($action == 'next') {$question_num ++;}
  177. // last button goes to the "end" page
  178. else if ($action == 'last')
  179. {
  180. header ("Location: ".END_FILE);
  181. exit (0);
  182. /* if ($question_num >= $num_questions)
  183. // old comment // special case with last button - if we are on last page then it goes to review (same as next button)
  184. {
  185. header ("Location: ".END_FILE);
  186. exit (0);
  187. }
  188. else
  189. {
  190. $question_num = $num_questions;
  191. }*/
  192. }
  193. // Handle change in page (eg. Finish / trying to go past first)
  194. if ($question_num < 1) {$question_num = 1;}
  195. if ($question_num > $num_questions || $action == 'review')
  196. {
  197. header ("Location: ".END_FILE);
  198. exit (0);
  199. }
  200. // Set variables prior to loading template
  201. $settings->setTempSetting ("quiz_title", $quiz_info['quiztitle']);
  202. $settings->setTempSetting ("question_number", $question_num);
  203. // Pull in templates
  204. $templates->includeTemplate('header', 'normal');
  205. // start form
  206. // Form starts at the top
  207. print "<form id=\"".CSS_ID_FORM."\" method=\"post\" action=\"".QUESTION_FILE."\">\n";
  208. // show message if there is one
  209. if ($message != '') {print "<p class=\"".CSS_CLASS_MESSAGE."\">$message</p>\n";}
  210. // show position in quiz
  211. // todo may want to allow this wording to be changed via a setting
  212. print "<p class=\"".CSS_CLASS_STATUS."\">Question $question_num of $num_questions</p>\n";
  213. // load this question - note -1 used to select array position (ie. question 1 = array 0)
  214. $question = new Question($qdb->getQuestion($questions_array[$question_num-1]));
  215. // first print status bar if req'd (eg. question 1 of 10)
  216. // answer is currently selected -1 = not answered
  217. print ($question->getHtmlString($quiz_session->getAnswer($question_num-1)));
  218. // add navigation buttons
  219. print "<div id=\"".CSS_ID_NAVIGATION."\">\n";
  220. $navigation->showNavigation($question_num);
  221. print "\n</div><!-- ".CSS_ID_NAVIGATION." -->\n";
  222. // end form
  223. print "</form>\n";
  224. // footer templates
  225. $templates->includeTemplate('footer', 'normal');
  226. // Debug mode - display any errors / warnings
  227. if (isset($debug) && $debug)
  228. {
  229. $err = Errors::getInstance();
  230. if ($err->numEvents(INFO_LEVEL) > 0)
  231. {
  232. print "Debug Messages:\n";
  233. print $err->listEvents(INFO_LEVEL);
  234. }
  235. }
  236. ?>