1

I need a way to restrict Quiz access for users who have achieved a passing grade to stop them retaking the quiz to gain more user points.

It displays "You have already passed this Quiz.", but I can't find an entity to check for it with the Rules module. Previous quiz result fields always return 0 which makes them worthless. Assigning roles won't work because I want to have quizzes daily.

Any hints?

PS: I'm using Quiz 7.x-5.1

2
  • Are you using the quizz module or a custom solution ? Commented Sep 7, 2017 at 15:52
  • The default Quiz module. 7.x-5.1
    – zoom-ping
    Commented Sep 7, 2017 at 18:14

1 Answer 1

1

Even though the Quiz 7.x-5.x release comes with lots of new Rules capabilities, I've not found any entity to check if a user already passed some quiz. However, using the Flag module you can implement an appropriate flag, and then just check if the quiz node (an entity ...) was flagged by the current user. Read on for how to do so ...

Step 1 - Create a flag for tracking Passed Quizes

Use the Flag module to create a flag labeled (e.g) Passed Quizes. Here is an export of the flag I used for this (you should be able to import it in your own site also):

$flags = array();
// Exported flag: "Passed Quizes".
$flags['passed_quizes'] = array (
  'entity_type' => 'node',
  'title' => 'Passed Quizes',
  'global' => '0',
  'types' => 
  array (
    0 => 'quiz',
  ),
  'flag_short' => 'Flag this item',
  'flag_long' => '',
  'flag_message' => '',
  'unflag_short' => 'Unflag this item',
  'unflag_long' => '',
  'unflag_message' => '',
  'unflag_denied_text' => '',
  'link_type' => 'toggle',
  'weight' => 0,
  'show_in_links' => 
  array (
    'full' => 'full',
    'teaser' => 'teaser',
    'rss' => 0,
    'search_index' => 0,
    'search_result' => 0,
    'answers_full_node' => 0,
    'print' => 0,
    'question' => 0,
    'token' => 0,
  ),
  'show_as_field' => 0,
  'show_on_form' => 0,
  'access_author' => '',
  'show_contextual_link' => 0,
  'i18n' => 0,
  'api_version' => 3,
);
return $flags;

This flag will be used in the custom rule, detailed in the next step.

Step 2 - Flag a Quiz node after passing the quiz

Create a custom rule to flag the quiz node (using the flag from Step 1) after a user passed the quiz and which looks like so (in Rules export format):

{ "rules_flag_a_quiz_when_passed_the_very_first_time" : {
    "LABEL" : "Flag a quiz when passed the very first time",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "TAGS" : [ "quiz" ],
    "REQUIRES" : [ "rules", "flag", "entity" ],
    "ON" : { "quiz_result_update" : [], "quiz_result_insert" : [] },
    "IF" : [
      { "entity_is_of_type" : { "entity" : [ "quiz-result:nid" ], "type" : "node" } },
      { "data_is" : { "data" : [ "quiz-result-unchanged:is-evaluated" ], "value" : "0" } },
      { "data_is" : { "data" : [ "quiz-result:is-evaluated" ], "value" : "1" } },
      { "NOT data_is" : {
          "data" : [ "quiz-result:score" ],
          "op" : "\u003C",
          "value" : [ "quiz-result:nid:quiz:pass-rate" ]
        }
      },
      { "NOT flag_flagged_node" : {
          "flag" : "passed_quizes",
          "node" : [ "quiz-result:nid" ],
          "flagging_user" : [ "site:current-user" ]
        }
      }
    ],
    "DO" : [
      { "drupal_message" : { "message" : "Congratulations, this is the FIRST time you passed this quiz (with a score of [quiz-result:score] %, whereas the pass rate is [quiz-result:nid:quiz:pass-rate] %)." } },
      { "flag_flagnode" : {
          "flag" : "passed_quizes",
          "node" : [ "quiz-result:nid" ],
          "flagging_user" : [ "site:current-user" ],
          "permission_check" : "1"
        }
      }
    ]
  }
}

Step 3 - Create a rule to disallow taking a passed quiz again

Here is a rule which illustrates how to resolve the challenge in your question:

{ "rules_disallow_taking_a_passed_quiz_again" : {
    "LABEL" : "Disallow taking a passed quiz again",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "flag", "entity" ],
    "ON" : { "quiz_result_insert" : [] },
    "IF" : [
      { "entity_is_of_type" : { "entity" : [ "quiz-result:nid" ], "type" : "node" } },
      { "flag_flagged_node" : {
          "flag" : "passed_quizes",
          "node" : [ "quiz-result:nid" ],
          "flagging_user" : [ "site:current-user" ]
        }
      }
    ],
    "DO" : [
      { "entity_delete" : { "data" : [ "quiz-result" ] } },
      { "drupal_message" : {
          "message" : "You already took (and passed) this quiz. Your new attempt to take it again has been disregarded and you have been redirected to your results summary ...",
          "type" : "warning"
        }
      },
      { "redirect" : { "url" : "[quiz-result:nid:url]\/quiz-results" } }
    ]
  }
}

Here are the critical pieces of this rule to make Rules-magic happen:

  • The Rules Event "After saving a new Quiz result" is what gets triggered right after a user attempts to start taking a quiz (a first time, or another time), so even before the first question of a quiz is shown.
  • The first Rules Condition, which is "the" way to get access to all sorts of data about the quiz node itself (starting from "a" quiz result).
  • The last Rules Condition, which verifies if the quiz node (to which this quiz result relates) is already flagged (by the flag from Step 1), which indicates this user already passed this quiz.

If all Rules Conditions are satisfied, then these Rules Actions will be executed:

  • Delete the newly created "quiz result" entity (this is needed, otherwise if the user would try another time to take the quiz, it would be considered as an attempt to resume taking the quiz, starting from the very first question, and the used Rules Event would NOT (repeat: NOT) be triggered ...).
  • Show an appropriate message.
  • Perform a redirect (to show the result summary of the quiz for the current user), to relative path node/nid/quiz-results (using nid as the node id of the quiz).

Use the Rules UI to import the above 2 rules in your own site, after you completed Step 1.

Showtime

Here is a sample of a warning message I received after passing a quiz, and trying to take the quiz again:

You already took (and passed) this quiz. Your new attempt to take it again has been disregarded and you have been redirected to your results summary ...

1
  • @zoom-ping merci for the feedback, and accept / +1 ... Next question? Commented Sep 12, 2017 at 9:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.