Skip to main content

Insight | Nov 13, 2015

Customizing the Quiz Module for Every Need in Drupal

By Josh Fremer

The Drupal Quiz module provides a great foundation to build scored assessments in Drupal. It offers a range of scoring customizations, but it can't fill every need out of the box.

Fortunately, Quiz also offers robust API exposed through a collection of hooks. If you have custom logic that impacts your scoring, hook_quiz_finished is for you. This hook allows you to modify any properties of a quiz result when it's saved.

In my case, I had the requirement that any questions answered "N/A" should be subtracted from the denominator of the scoring equation. So, for instance, if a quiz had 10 questions and had 1 correct answer, 1 incorrect answer and 8 "N/A", the quiz score would be 50% (1/2).

 

/**
 * Implements hook_quiz_finished().
 *
 * If a question is answered "N/A", that question doesn't count toward the total
 * possible score.
 */
function mymodule_quiz_finished($quiz, $score, $data) {
  $possible_score = $score['possible_score'];
 
  // Here we're going to count up the number of 'N/A' answers.
  $query = db_select('quiz_node_results_answers', 'qra');
  $query->join('quiz_multichoice_user_answers', 'qmua', 'qra.result_answer_id = qmua.result_answer_id');
  $query->join('quiz_multichoice_user_answer_multi', 'qmuam', 'qmua.id = qmuam.user_answer_id');
  $query->join('quiz_multichoice_answers', 'qma', 'qmuam.answer_id = qma.id');
  $query->condition('qra.result_id', $data['result_id']);
  $query->condition('qma.answer', t('N/A'));
  $query->fields('qra', array('result_answer_id'));
 
  $na_answers = $query->execute()->rowCount();
 
  // Subtract the total from the highest possible score.
  $possible_score = $possible_score - $na_answers;
 
  // Then recalculate the score.
  $quiz_result = quiz_result_load($data['result_id']);
  if ($possible_score > 0) {
    $quiz_result->score = ($score['numeric_score'] / $possible_score) * 100;
  }
  else {
    $quiz_result->score = 0;
  }
  entity_save('quiz_result', $quiz_result);
}

 

hook_quiz_finished implementations take three arguments:

  1. The quiz entity for which a new result was recorded.
  2. An associative array of scoring data, including possible_score (the number of total questions encountered) and numeric_score (the number of correct answers).
  3. An associative array of information about the quiz result record, including result_id which you can use to load the full result entity for updating.

In my example above I query for a count of all "N/A" answers recorded for the quiz result in question (this takes a few joins). Then I simply subtract that count from the number of possible answers and re-calculate the score. As far as the Drupal Quiz module is concerned, scoring is finished for this result; it never goes back and re-calculates so your custom-calculated score is safe and ready for display.

Drop us a line

Have a project in mind?

Contacting Third and Grove may cause awesomeness. Side effects include a website too good to ignore. Proceed at your own risk.

Get a fresh perspective on your digital future. The best of TAG, straight to your inbox.

Subscribe to newsletter

By signing up for emails from Third and Grove, you agree to our Privacy Policy. We handle your info with care. Unsubscribe anytime.

Copyright © 2026 Third and Grove

Reduced motion disabled