Index: quiz.module =================================================================== --- quiz.module (revision 6014) +++ quiz.module (working copy) @@ -425,7 +425,7 @@ 'file' => 'quiz.pages.inc', ), 'quiz_progress' => array( - 'arguments' => array('question_number' => NULL, 'num_of_question' => NULL), + 'arguments' => array('question_number' => NULL, 'num_of_question' => NULL, 'quiz' => NULL), 'file' => 'quiz.pages.inc', ), 'quiz_no_feedback' => array( @@ -440,6 +440,10 @@ 'file' => 'quiz.pages.inc', 'arguments' => array('question_node' => NULL), ), + 'quiz_multi_question_node' => array( + 'file' => 'quiz.pages.inc', + 'arguments' => array('question_node' => NULL), + ), 'question_selection_table' => array( 'file' => 'quiz.admin.inc', 'arguments' => array('form' => array()), @@ -534,12 +538,12 @@ backwards_navigation, repeat_until_correct, quiz_open, quiz_close, takes, show_attempt_stats, keep_results, time_limit, pass_rate, summary_pass, summary_default, quiz_always, feedback_time, display_feedback, tid, - has_userpoints, allow_skipping) + has_userpoints, allow_skipping, single_page) VALUES(%d, %d, '%s', %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, '%s', '%s', %d, %d, %d, %d, - %d, %d)"; + %d, %d, %d)"; // If the quiz is saved as not randomized we have to make sure that questions belonging to the quiz are saved as not random _quiz_check_num_random($node); @@ -548,7 +552,7 @@ $node->backwards_navigation, $node->repeat_until_correct, $node->quiz_open, $node->quiz_close, $node->takes, $node->show_attempt_stats, $node->keep_results, $node->time_limit, $node->pass_rate, $node->summary_pass, $node->summary_default, $node->quiz_always, $node->feedback_time, $node->display_feedback, $tid, - isset($node->has_userpoints) ? $node->has_userpoints : 0, $node->allow_skipping); + isset($node->has_userpoints) ? $node->has_userpoints : 0, $node->allow_skipping, $node->single_page); _quiz_insert_resultoptions($node); @@ -609,13 +613,14 @@ display_feedback = %d, number_of_random_questions = %d, has_userpoints = %d, - allow_skipping = %d + allow_skipping = %d, + single_page = %d WHERE vid = %d AND nid = %d"; _quiz_check_num_random($node); $resource = db_query($sql, $node->vid, $node->aid, $node->randomization, $node->backwards_navigation, $node->repeat_until_correct, $node->quiz_open, $node->quiz_close, $node->takes, $node->show_attempt_stats, $node->keep_results, $node->time_limit, $node->pass_rate, $node->summary_pass, $node->summary_default, $node->quiz_always, - $node->feedback_time, $node->display_feedback, $node->number_of_random_questions, isset($node->has_userpoints) ? $node->has_userpoints : 0, $node->allow_skipping, + $node->feedback_time, $node->display_feedback, $node->number_of_random_questions, isset($node->has_userpoints) ? $node->has_userpoints : 0, $node->allow_skipping, $node->single_page, $node->vid, $node->nid); _quiz_update_resultoptions($node); } @@ -688,6 +693,7 @@ 'tid' => 0, 'has_userpoints' => 0, 'allow_skipping' => 1, + 'single_page' => 0, ); } @@ -863,6 +869,12 @@ '#default_value' => $node->allow_skipping, '#description' => t('Whether to allow users to skip questions in the @quiz', array('@quiz' => QUIZ_NAME)), ); + $form['taking']['single_page'] = array( + '#type' => 'checkbox', + '#title' => t('Show all questions on a single page'), + '#default_value' => $node->single_page, + '#description' => t('Whether to show all questions on a single page in the @quiz', array('@quiz' => QUIZ_NAME)), + ); $form['taking']['backwards_navigation'] = array( '#type' => 'checkbox', '#title' => t('Backwards navigation'), @@ -1493,6 +1505,9 @@ function quiz_take_quiz($quiz) { global $user; $allow_skipping = $quiz->allow_skipping; + if ($quiz->single_page) { + $_POST['tries'] == '1'; + } if (!isset($quiz)) { drupal_not_found(); @@ -1512,7 +1527,7 @@ } // If the session has no data for this quiz. - if (!isset($_SESSION['quiz_'. $quiz->nid]['quiz_questions'])) { + if ($quiz->single_page || !isset($_SESSION['quiz_'. $quiz->nid]['quiz_questions'])) { // We delete questions in progress from old revisions. _quiz_delete_old_in_progress($quiz, $user->uid); @@ -1521,7 +1536,8 @@ $rid = _quiz_active_result_id($user->uid, $quiz->nid, $quiz->vid); // Are we resuming an in-progress quiz? - if ($rid > 0) { + // We can't resume single page quizzes. + if (!$quiz->single_page && $rid > 0) { _quiz_resume_existing_quiz($quiz, $user->uid, $rid); } // First time running through quiz. @@ -1549,6 +1565,7 @@ $_SESSION['quiz_'. $quiz->nid]['question_start_time'] = time(); $_SESSION['quiz_'. $quiz->nid]['question_duration'] = $quiz->time_limit; $_SESSION['quiz_'. $quiz->nid]['quiz_vid'] = $quiz->vid; + $_SESSION['current_quiz_id'] = $quiz->nid; } else { @@ -1565,7 +1582,7 @@ if (!isset($_POST['op'])) { // @todo Starting new quiz... Do we need to show instructions here? } - elseif ($_POST['question_nid'] != $_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['nid']) { + elseif (!$quiz->single_page && $_POST['question_nid'] != $_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['nid']) { // The user has pressed the navigation buttons multiple times... } // We maintain two lists: previous questions and upcomming questions. @@ -1584,14 +1601,35 @@ $former_question_array = array_shift($_SESSION['quiz_'. $quiz->nid]['quiz_questions']); $former_question = node_load($former_question_array['nid'], $former_question_array['vid']); - // Call hook_evaluate_question(). - $types = _quiz_get_question_types(); - $module = $types[$former_question->type]['module']; - $result = module_invoke($module, 'evaluate_question', $former_question, $_SESSION['quiz_'. $quiz->nid]['result_id']); - $q_passed_validation = $result->is_valid; - if ($q_passed_validation === TRUE) { - quiz_store_question_result($quiz, $result, array('set_msg' => TRUE)); + if (!$quiz->single_page) { + // Call hook_evaluate_question(). + $types = _quiz_get_question_types(); + $module = $types[$former_question->type]['module']; + $result = module_invoke($module, 'evaluate_question', $former_question, $_SESSION['quiz_'. $quiz->nid]['result_id']); + $q_passed_validation = $result->is_valid; + if ($q_passed_validation === TRUE) { + quiz_store_question_result($quiz, $result, array('set_msg' => TRUE)); + } } + else { + foreach ($questions as $question) { + $former_question = node_load($question['nid'], $question['vid']); + $_POST['tries'] = $_POST['tries_' . $question['nid']]; + // Call hook_evaluate_question() for each question. + $types = _quiz_get_question_types(); + $module = $types[$former_question->type]['module']; + $result = module_invoke($module, 'evaluate_question', $former_question, $_SESSION['quiz_'. $quiz->nid]['result_id']); + $q_passed_validation = $result->is_valid; + if (false && $q_passed_validation != 1) { + /** Very basic validation. TODO: save form values. */ + drupal_set_message('Please check your submission for errors.','error'); + quiz_delete_results(array($_SESSION['quiz_'. $quiz->nid]['result_id'])); + drupal_goto("node/{$quiz->nid}/take"); + } + quiz_store_question_result($quiz, $result, array('set_msg' => TRUE)); + } + $quiz_end = TRUE; + } // Stash feedback in the session, since the $_POST gets cleared. if ($quiz->feedback_time == QUIZ_FEEDBACK_QUESTION && $_POST['op'] != t('Back') && $q_passed_validation === TRUE) { @@ -1655,6 +1693,12 @@ $_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['nid'], $_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['vid'] ); + if ($quiz->single_page) { + $question_node_multi = array(); + foreach($questions as $question) { + array_push($question_node_multi,node_load($question['nid'], $question['vid'])); + } + } if (isset($_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['rid'])) $question_node->rid = $_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['rid']; // We got an error message when trying to validate the previous answer @@ -1676,7 +1720,7 @@ $number_of_questions = quiz_get_number_of_questions($quiz->vid); $question_number = $number_of_questions - count($_SESSION['quiz_'. $quiz->nid]['quiz_questions']); $question_node->question_number = $question_number; - $content['progress']['#value'] = theme('quiz_progress', $question_number, $number_of_questions); + $content['progress']['#value'] = theme('quiz_progress', $question_number, $number_of_questions, $quiz); $content['progress']['#weight'] = -50; if (count($_SESSION['quiz_'. $quiz->nid]['quiz_questions']) + count($_SESSION['quiz_'. $quiz->nid]['previous_quiz_questions']) > $number_of_questions) { drupal_set_message(t('At least one question have been deleted from the quiz after you started taking it. You will have to start over.'), 'warning', FALSE); @@ -1744,7 +1788,12 @@ } // If we're not yet at the end. if (empty($quiz_end)) { + if (!$quiz->single_page) { $content['body']['question']['#value'] = quiz_take_question_view($question_node, $quiz); + } + else { + $content['body']['question']['#value'] = quiz_node_view_multi($question_node_multi, TRUE, FALSE); + } $content['body']['question']['#weight'] = 0; // If we had feedback from the last question. if (isset($_SESSION['quiz_'. $quiz->nid]['feedback']) && $quiz->feedback_time == QUIZ_FEEDBACK_QUESTION) { @@ -1805,6 +1854,25 @@ } /** + * Create the view for a multi-question the user is about to take. + * + * @param $question_nodes + * The question nodes that should be rendered. + * @param $quiz_node + * The quiz node. + * @return + * A string containing the body of the node. + */ +function quiz_node_view_multi($question_nodes = array(), $quiz_node) { + foreach($question_nodes as &$question_node) { + $question_node = node_build_content($question_node, FALSE, TRUE); + node_invoke_nodeapi($question_node, 'alter', FALSE, TRUE); + $question_node->body = drupal_render($question_node->content); + } + return theme('quiz_multi_question_node', $question_nodes); +} + +/** * Store a quiz question result. * * @param $quiz Index: quiz.pages.inc =================================================================== --- quiz.pages.inc (revision 6014) +++ quiz.pages.inc (working copy) @@ -341,7 +341,7 @@ * * @ingroup themeable */ -function theme_quiz_progress($question_number, $num_of_question) { +function theme_quiz_progress($question_number, $num_of_question, $quiz) { // Determine the percentage finished (not used, but left here for other implementations). //$progress = ($question_number*100)/$num_of_question; @@ -350,7 +350,12 @@ $output = ''; $output .= '