I'm trying to use a quiz to assign a user role. If the quiz is passed, the user gets the role. I can't figure out a way to use passing the quiz as a trigger with the Rules module, or any other way. I also know next to nothing about editing the code myself to do it manually, but am very willing to try any suggestions :3.

Comments

v-a-1’s picture

I am trying to do something similar. I am trying to issue a certificate on quiz completion.
But as above, I am not sure how to capture the quiz passing event as a trigger for rules.
Any help much appreciated.

v-a-1’s picture

I did manage to figure this out.
I am posting the relevant bits of code here for the original poster.

Create a rule "on content going to be viewed".
Make sure you have php filter module turned on in site building.
In the rule select "execute custom php code" as action. No conditions are required.

I used the following code to iterate through quizzes, figure out if user has passed and do relevant action.


   // get details of quizzes attempted for the current user
	$result = db_query_range( 'SELECT n.nid, n.score, n.vid, n.time_end 
                                FROM {quiz_node_results} n 
                                WHERE n.uid = %d', $user->uid, 0, 1000 );

    // now iterate through result
	while ( $r = db_fetch_object( $result ) ) {
		$quizvid = $r->vid;

		// now get pass rate for each quiz node using vid. each vid might have different pass rates
		// so dont use nid
		$res = db_query( 'SELECT n.pass_rate
                            FROM {quiz_node_properties} n 
                            WHERE n.vid = %d', $quizvid );
                            
        // iterate through result
		while ( $r2 = db_fetch_object( $res ) ) {
		  
			// if score is equal or higher than pass rate,
			// user has already passed the test. testing against nid, because future revisions
			// might end up making a user un-passed. so dont use vid here.
			if ( $r->score >= $r2->pass_rate ) {
				//DO WHATEVER ACTION CODE HERE
				//LIKE ASSIGNING ROLE TO USER
				//not sure how it works. i am sure you can find it if you search for it.
			}
			else {
			}

		}

	}

Buddhist’s picture

thanks a lot :3!

The code I'm using to add the role is this:

global $user; // Retrieve user object for currently logged in user.

		  $role_name = 'YOUR ROLE TO ADD'; // Name of role to add, e.g. administrator, moderator, etc

		  // Get RID of role
		  $rid = db_result(db_query("SELECT r.rid FROM {role} r WHERE r.name = '%s'", $role_name));

		  // Save the user object with the new role.
  		if (!isset($user->roles[$rid])) {
    		$roles = $user->roles + array($rid => $role_name);
    		user_save($user, array('roles' => $roles));
  		}

works quite well :3

v-a-1’s picture

Thats great, and thanks for the update.

Buddhist’s picture

Status: Active » Closed (fixed)
Rosamunda’s picture

I´ve followed the instructions but I can´t save the PHP action. It goes to Page not found...

v-a-1’s picture

That makes very little sense to me. You will have to be more specific with your question. What exactly did you do, and where exactly is the problem.

Rosamunda’s picture

Thanks for your reply!

This is what I´ve done:
Created a rule "on content going to be viewed".
Inside the rule, I selected "execute custom php code" as action. (the PHP filter module is active)
I added the following code to it:

<?php
   // get details of quizzes attempted for the current user
    $result = db_query_range( 'SELECT n.nid, n.score, n.vid, n.time_end 
                                FROM {quiz_node_results} n 
                                WHERE n.uid = %d', $user->uid, 0, 1000 );

    // now iterate through result
    while ( $r = db_fetch_object( $result ) ) {
        $quizvid = $r->vid;

        // now get pass rate for each quiz node using vid. each vid might have different pass rates
        // so dont use nid
        $res = db_query( 'SELECT n.pass_rate
                            FROM {quiz_node_properties} n 
                            WHERE n.vid = %d', $quizvid );
                            
        // iterate through result
        while ( $r2 = db_fetch_object( $res ) ) {
          
            // if score is equal or higher than pass rate,
            // user has already passed the test. testing against nid, because future revisions
            // might end up making a user un-passed. so dont use vid here.
            if ( $r->score >= $r2->pass_rate ) {

global $user; // Retrieve user object for currently logged in user.

		  $role_name = 'alumno1'; // Name of role to add, e.g. administrator, moderator, etc

		  // Get RID of role
                  // I just want to add a new role, so I comment this one, saving it for... maybe later?
		  //$rid = db_result(db_query("SELECT r.rid FROM {role} r WHERE r.name = '%s'", $role_name));

		  // Save the user object with the new role.
  		if (!isset($user->roles[$rid])) {
    		$roles = $user->roles + array($rid => $role_name);
    		user_save($user, array('roles' => $roles));
  		}
            }
            else {
            }

        }

    }
?>

I didn´t add the <?php ?> tags.

When I hit save, it goes to 404 not found.
I´ve tried several times, and the error is still there.

Thanks!
Rosamunda

v-a-1’s picture

This doesn't look like a problem with the code or the rules module. More likely you have some path module enabled that's messing with the system. Try disabling any path modules and trying again. If it still persists we can take it from there.

FilipNest’s picture

Title: Using a passed quiz to add a role to a user » Using a passed quiz to trigger a rules action
Version: 6.x-4.1 » 7.x-4.x-dev
Status: Closed (fixed) » Active

Does anyone know how you could do this (or perform any other rule action after a quiz is passed?) in Drupal 7?

I've tried a roundabout route by triggering a custom action at the end of the quiz that takes them to a URL, fires the rule that looks at a view which lists the tests the user has passed. Sadly there doesn't seem to be any way to filter by either passed tests or score in views (for Drupal 7, there does seem to be a patch for 6) so I'm stuck there.

Ideally there'd be a "A user passes a test" event in Rules.

Or a filter by pass or fail status in views.

Or even a filter by score in views.

I'm happy to just use a php snippet in Rules as above but am having no luck getting the above to work without error messages as things have probably changed in rules, core and quiz between Drupal versions.

Has anyone worked anything like this out for D7? This module is pretty close to perfect but this additional functionality would be really useful. Even a sepearate action for if the test has passed would just about work.

Thanks in advance for any help offered.

Rosamunda’s picture

Version: 7.x-4.x-dev » 6.x-4.1
Status: Active » Closed (fixed)

Thanks for your reply @voodoo.child.
I´ve had installed Globalredirect and Pathauto.
I´ve disabled both but the problem remains.

When I try to save, it redirects me to "Not Found The requested URL was not found on this server."
The redirected url is: http://www.mysite.com/admin/rules/rules/rules_cuestionario_est_por_ser_v...

Thankd for your help!!
Rosamunda

v-a-1’s picture

Ok. I would recommend two things: if possible, uninstall any of the path modules completely and flush all caches. Then see if the problem persists.
And second, make sure that your .htaccess file in the base drupal folder isn't messing with some of the paths.
And try and edit an existing rule (different from the one you are trying to save). See if that works.
Finally check the php version you are running on your server. There are sometimes conflicts between different versions of different modules and php. Especially with php 5.3, I've have the unfortunate experience of some of the modules not functioning correctly.
I actually downgraded a couple of my servers to 5.2 to make my sites run smoothly.

Report back with your findings and we can narrow down the problem.

v-a-1’s picture

@Blue_Jumpers_Filip

You really should create a separate issue with the version of drupal set to 7. This thread deals specifically with 6. You'd have a better chance of getting help, not to mention it makes logical sense.

Rosamunda’s picture

I´ll try that. My PHP version is 5.2.17.

FilipNest’s picture

Sorry! I thought it was closed and didn't want to muddle the issue queue too much.

batandwa.sb’s picture

Would I be correct in saying that Quiz has no Rules integration?

I don't find any options in Rules or Triggers. I supposed that is why this issue was opened.

freddura’s picture

You can imply a rules action when editing a quiz node, under "taking options" click the drop down for "Assign action" and click "save content." Now, got into rules and create a rule:

event: after updating existing content
condition: content is of type = quiz

Each time the user completes a quiz, the rule will be triggered. If you would like to set a condition to determine if the user has passed the quiz, you must first create a VBO view that takes the arguments/contextual filters: •current user
•updated node.

Also for the view add a filter for Quiz Results: Score (>75) (or whatever your score threshold is for a passed quiz)

Under the rules conditions select: "Check number of results returned by a VBO view," and select you newly created view. Use the current user as the first argument, and the update node as the second argument. Set minimum number of results to 1.

This will rule will evaluate each time a user takes a quiz and passes. This may not be the most ideal way to "Using a passed quiz to trigger a rules action" but it should work. Hope this helps and good luck!

japo32’s picture

is there a way to do this in Drupal 6?

japo32’s picture

Ok I figured out how to do this using Rules and Rules Scheduler in Drupal 6. I was lucky to discover that Rules Scheduler can run a certain set of Rules after a certain amount of time. I also used some Executed PHP code for the Condition to determine if the User has passed the quiz.

My requirement was to send an email to a user a few months after they have passed the quiz. This is for a purpose similar to driver's license renewal - for continuous accreditation.

Here's what I did:

  1. Added a new field to Quiz called Months Valid. This is a select list integer.
  2. Create a a RuleSet named Send Email to User that takes in arguments User and Content
  3. in this Ruleset I added one rule: send email.
    IF TRUE DO Send an HTML email (courtesy of MIME Mail) to the User with a customized message.
  4. Then I created a Triggered Rule After updating existing content Which fires IF Updated Content is Quiz AND Execute Custom PHP Code returns true:
    $sql = 'SELECT n.title, rr.score AS percent_score, p.pass_rate AS percent_pass, n.nid AS node_id, nr.vid AS revision_id, p.vid AS np_vid, rr.time_end AS end_time FROM node n 
    INNER JOIN node_revisions nr ON n.vid = nr.vid
    INNER JOIN quiz_node_properties p ON nr.vid = p.vid 
    INNER JOIN (SELECT * FROM quiz_node_results r WHERE r.uid = %d ORDER BY r.vid DESC LIMIT 1) AS rr ON rr.nid = n.nid
    WHERE n.vid = %d AND nr.uid = %d AND rr.score >= p.pass_rate';
    
    $result = db_query($sql, $user->uid, $node->vid, $user->uid);
    $return_this = FALSE;
    $rows = array();
    
    while ($row = db_fetch_array($result)) {
    $rows[] = $row;
    }
    
    if( empty($rows) ){        
    }else{
    	$return_this = TRUE;
    }
    
    return $return_this;
    

    Basically this determines if the updated quiz taken by the user has a higher score than the passing rate. I had to go this route since I was using Drupal 6. So the VBO result to evaluate is not yet included. This took me some time to figure out and I used print theme('table', $header, $rows); heavily to debug.

  5. This Triggered rule then does the following:
    Show a Configurable Message to notify the user
    and Schedule "Send Email to User".
    You can find Schedule under Rules Scheduler in the drop down Select an action to add.

    For the arguments I used the updated content and the acting user.

    In Scheduled evaluation date I put in +[node:field_months_valid-raw] months.
    [node:field_months_valid-raw] is the token replacement for the new field I added to Quiz.
    When I was testing I changed the months to seconds. :)

Works like a charm. :)

dadderley’s picture

Hi freddura,
Thanks for the tip on how to get Quiz to fire a Rule.
I now have Quiz firing a Rule that adds data to another node (a node with fields to show the user has taken individual quizzes). I mention your post over here http://drupal.org/node/1689358#comment-6560536 in the Conditional Rules http://drupal.org/project/rules_conditional issue page.
This is all good.

I am trying to implement this part of your advice.

If you would like to set a condition to determine if the user has passed the quiz, you must first create a VBO view that takes the arguments/contextual filters: •current user
•updated node.
Also for the view add a filter for Quiz Results: Score (>75) (or whatever your score threshold is for a passed quiz)

Under the rules conditions select: "Check number of results returned by a VBO view," and select you newly created view. Use the current user as the first argument, and the update node as the second argument. Set minimum number of results to 1.

I can't figure out how to set up this VBO view. Also I have never used VBO and Rules so I am really struggling with this.
Could you possibly give me a little more detail about how to set up this view.
Thanks in advance.

This is a Drupal 7 site.

tonyhrx’s picture

Following feddura's advice at 17 for Drupal 7
Don't know about anyone else but getting a VBO view for quiz was like having dentistry without anaesthetic.

Here's what I did though.

We need to create a quiz view that uses the currently logged in user UID and the quiz NID and a pass filter of 75%. If we get a view result then it evaluates to TRUE and we can progress with rule actions etc.

Creating that view can be done pretty easy. Follow feddura's advice.

Now install Rules Bonus. That has a feature that allows us to test if a view has results.

You need two rules.

The first is the trigger rule on After Updating Content (see feddura's advice). We check its a quiz node and then load the currently logged-in user using the Fetch Entity action. This is how we get the currently logged–in user.

We then pass these parameters over to a rule set.

The rule set has a rule that takes the user and nid parameters from the first rule and applies them to a 'Check number of results from a view' evaluation. If it returns true we get TRUE.

Must admit, all that is massively fiddly for such a small thing.

Looking forward to some coders better than me at doing a proper rules integration.

dadderley’s picture

@tonyhrx
I have to look into the methods you mention. Sound like it is the way to go.
I have been using Conditional Rules (http://drupal.org/project/rules_conditional) for lots of other stuff .
It is a super useful module.

ashish.mahajan’s picture

ashish.mahajan’s picture

Issue summary: View changes

Hello All,

I am stuck in one use case where I have to change the user role when taxonomy term is clicked/viewed. I am using Rules module, I have made following configurations:
1. Created rule called "Role Trigger" using Rules module.
2. Added the Event "Taxonomy term viewed".
3. Added action "Add User Role".
4. In user value field I have selected 'data selection' mode and given syntax for getting current user instance.
syntax: "@user.current_user_context:current_user"
5. Given role as "abc" using direct input mode.
So, potentially the user role gets changed to abc from existing role (lets say xyz). But it is not changing role and getting a white screen. Additionally, if i try to assign role as "taxonomy_term.name" using data selector mode, It gives me an error as Invalid Argument. I am stuck here very badly, I just wanted to change the role of the user when taxonomy term is viewed/clicked.
can anyone please help me figure this out? Thanks in Advance...