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 ...