Index: quiz.install
===================================================================
--- quiz.install (revision 5651)
+++ quiz.install (working copy)
@@ -8,6 +8,17 @@
*/
/**
+ * Implementation of hook_update_N()
+ *
+ * Adding a field to turn on/off showing all question on one page
+ */
+function quiz_update_6419() {
+ $result = array();
+ db_add_field($result, 'quiz_node_properties', 'single_page', array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0));
+ return $result;
+}
+
+/**
* Implementation of hook_update_N
*
* Change the primary key of the quiz_node_properties table to something more useful...
@@ -876,6 +887,12 @@
'not null' => TRUE,
'default' => 0,
),
+ 'single_page' => array(
+ 'type' => 'int',
+ 'size' => 'small',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
),
'primary key' => array('vid'),
// 'unique keys' => array('vid'),
Index: quiz.pages.inc
===================================================================
--- quiz.pages.inc (revision 5651)
+++ 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 .= '
';
- $output .= t('Question %x of %y', array('%x' => $current_question, '%y' => $num_of_question));
+ if ($quiz->single_page) {
+ $output .= format_plural($num_of_question, '1 question', '@count questions');
+ }
+ else {
+ $output .= t('Question %x of %y', array('%x' => $current_question, '%y' => $num_of_question));
+ }
$output .= '
'."\n";
// Add div to be used by jQuery countdown
$output .= '';
@@ -463,6 +468,31 @@
}
/**
+ * Theme the multi question node.
+ *
+ * @param $nodes
+ * The question nodes
+ * @return
+ * Themed html feedback
+ */
+function theme_quiz_multi_question_node($nodes = array()) {
+ $qno = 0;
+ foreach ($nodes as $node) {
+ $qno++;
+ preg_match('||si', $node->body, $matches);
+ $form_free_body = preg_replace('/]*?>/','',$matches[1]);
+ $item_list[] = array(
+ 'class' => "question-{$node->nid} question-number-$qno",
+ 'data' => str_replace('name="tries', 'name="tries_' . $node->nid . '', $form_free_body),
+ );
+ }
+ $output = '';
+ return $output;
+}
+
+/**
* Theme the stats on the views page
*
* @param $node
Index: quiz.module
===================================================================
--- quiz.module (revision 5651)
+++ 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()),
@@ -535,12 +539,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);
@@ -549,7 +553,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);
@@ -610,13 +614,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);
}
@@ -689,6 +694,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);
@@ -1549,6 +1564,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 {
@@ -1579,15 +1595,37 @@
$_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0]['rid'] = $_SESSION['quiz_' . $quiz->nid]['result_id'];
$_SESSION['quiz_'. $quiz->nid]['previous_quiz_questions'][] = $_SESSION['quiz_'. $quiz->nid]['quiz_questions'][0];
$former_question_array = array_shift($_SESSION['quiz_'. $quiz->nid]['quiz_questions']);
- $former_question = node_load($former_question_array['nid'], $former_question_array['vid']);
+ if (!$quiz->single_page) {
+ $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;
- quiz_store_question_result($quiz, $result, array('set_msg' => TRUE));
+ // Call hook_evaluate_question() for a single 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;
+ 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 ($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) {
// Invoke hook_get_report().
@@ -1649,6 +1687,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
@@ -1665,7 +1709,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);
@@ -1733,7 +1777,12 @@
}
// If we're not yet at the end.
if (empty($quiz_end)) {
- $content['body']['question']['#value'] = quiz_take_question_view($question_node, $quiz);
+ 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) {
@@ -1794,6 +1843,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