15 replies [Last post]
Neutrino's picture
Offline
Joined: 08/08/2008
Juice: 14
Was this information Helpful?

I need to remove a users old role in addition to adding a new one after a purchase is complete.
I've looked around in drupal and haven't found any way to do this. The reason for removing the old role is to hide the membership product from the user unless their role expires (I assume after I figure out how to remove a role I'll know enough to add it back so they can purchase membership again).

using drupal 6.10 and ubercart 2.x

thanks.

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Re: need to remove role on purchase

At this point, you'd need a custom PHP action in your CA predicate to remove the role. I don't believe we have such an action coded.

Neutrino's picture
Offline
Joined: 08/08/2008
Juice: 14
Re: Re: need to remove role on purchase

I figured as much after searching through websites and irc's.
I'm not very good at PHP yet, particularly in relation to drupal. do you have any suggestions where I can find/learn such code?

Neutrino's picture
Offline
Joined: 08/08/2008
Juice: 14
ok I almost have it but.....

I'm down to needing to get the user id from the order, but I can't figure out how. I thought maybe $updated_order was the order id and I was wrong. Is it an array?

--edit--
I finally figured it out.

//grab user in question
$user_id = $updated_order->uid;

//find the id for role "contractor";
$sql_get_role = "SELECT rid FROM role WHERE name ='contractor'";
$role_id = db_result(db_query($sql_get_role));

//remove contractor role
$sql_remove_role = "DELETE FROM `users_roles` WHERE uid = $user_id AND rid = $role_id";
db_query($sql_remove_role);

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Re: ok I almost have it but.....

Looks great! Just a couple quick tips on using the database abstraction layer in Drupal (i.e. the set of functions you use to run queries). You should wrap table names in curly braces and use arguments to the db_query() function instead of inserting your variables directly:

<?php
//grab user in question
$user_id = $updated_order->uid;

//find the id for role "contractor";
$role_id = db_result(db_query("SELECT rid FROM {role} WHERE name = 'contractor'"));

//remove contractor role
db_query("DELETE FROM {users_roles} WHERE uid = %d AND rid = %d", $user_id, $role_id);
?>

It's not a big security risk here, but it could be for other queries so it's best to be in the habit. Smiling

Also, except in rare cases, queries are generally not built in separate variables, though that's totally up to you. I like having the query as a function argument so I can more easily see the mapping of placeholders -> arguments.

Neutrino's picture
Offline
Joined: 08/08/2008
Juice: 14
Re: Re: ok I almost have it but.....

ok. Thanks for the tips Smiling

originalgravity's picture
Offline
Joined: 07/14/2009
Juice: 2
Re: Re: Re: ok I almost have it but.....

did you ever get this working? can you share the code you used for the CA? I've searched this site, drupal.org and the general internet looking for a way to remove one role upon purchase of a different role, and this is the closest it looks like anyone has gotten.

thanks for any help.

Francois's picture
Offline
Joined: 08/19/2008
Juice: 387
Ditto

I'm also looking to do this. I tried running the PHP upstairs in CA but to no avail. What exact steps do you need to take for this to work?

Thanks! Smiling

--------
'Twas the end of the world, and you didn't even know it.

jusspitti's picture
Offline
Joined: 11/13/2009
Juice: 5
Feature Request

I think we should make this a feature request

jusspitti's picture
Offline
Joined: 11/13/2009
Juice: 5
finally!

I managed to make this php hieroglyphs works Eye-wink

1. You have to create the Conditional Action Trigger Order status gets updated
2. You have to make sure is below Grant or renew purchased roles
3. Add conditions for checking if the user have the roles in question (Condition: Check the role of the user.)
4. These conditions argument is updated order
5. Save and go to actions
6. add Execute php code action
7. Paste the php code mentioned upstairs without the

<?php

?>

8. Replace "contractor" with the exact name of the role you want to remove
9. Add the Action: Display a message to the user (this is like a debug echo in our case to check if the condition is being triggered)
10. Save

Done Smiling

vensires's picture
Offline
Joined: 07/30/2010
Juice: 65
uc_myca_module

I also created a trigger module. It must be below "Grant or renew purchased roles"(as stated above) and it assumes that the only way for the user to obtain roles is through an ubercart store. Below is the action function and attached is the module itself.

<?php
/**
* Delete all product roles from user (except authenticated role).
*
* This function deletes all roles of the user.
* We assume that:
* (a)the only way for a user to obtain a role is through the uc store
* (b)users can have only two roles:
*  (i) authenticated user
*  (ii) a role bought from ubercart
* (c)authentintaced role never has an expiry date
* Explanation:
*  When a user buys a subscription plan(ubercart product)
*  all roles are deleted, except authenticated role.
* @param $order
*  An Ubercart order object.
*/
function uc_myca_action_order_delete($order, $settings) {
 
// Load the order's user and exit if not available.
 
if(!($account = user_load($order-&gt;uid))){
    return;
  }
 
//{users_roles} only has extra roles. nor "authenticated" nor "anonymous"
 
db_query("DELETE FROM {users_roles} WHERE uid = %d", $account-&gt;uid);
}
?>
AttachmentSize
uc_myca.module 3.14 KB
vensires's picture
Offline
Joined: 07/30/2010
Juice: 65
Rewrite uc_myca_action_order_delete(): Multiple roles supported

I remade my previous function uc_myca_action_order_delete() to something more complicated but which supports many roles per user. Attached is the new module file. The $extra_roles array variable should better be stored in a drupal variable through a admin_form_page but for now I think it's fine.

Notice: The $extra_roles array contains the extra roles case-insensitive.

<?php
/*
* This function deletes all ubercart roles of the user except the one
* to be renewed(if renew is applicable) and any extra roles.
* We assume that the only way for roles, associated with ubercart
* products, to be given, is by buying the associated products. If more
* roles exist, that are given by ex. the admin(uid=1), these roles are
* defined in the $extra_roles variable array.
* @param $order
*   An Ubercart order object.
*/
function uc_myca_action_order_delete($order, $settings) {
 
// Load the order's user and exit if not available.
 
if(!($account = user_load($order->uid))){
    return;
  }
 
$product = $order->products[0];
 
$pid = $product->nid;
 
 
$features = db_fetch_array(db_query("SELECT description FROM {uc_product_features} WHERE nid='%d' AND fid='role'",$pid));
 
$str = $features['description'];
 
 
//processing the description string
 
$str = str_replace("<strong>","",$str); //remove <strong>
 
$str = str_replace("</strong>","",$str); //remove </strong>
 
$str = explode("<br />",$str);
 
/*
   * $str at this points seems like
   * Array(
   *  [0] => SKU: sku_here
   *  [1] => Role: role_name_here
   *  [2] => Expiration: 1 year(s)
   *  [3] => Shippable: No
   *  [4] => Multiply by quantity: No
   * )
   */
 
$keys = array_keys($str);
  foreach(
$keys as $key){
   
$value = explode(": ",$str[$key]);
   
$str[$key] = $value;
  }
 
/*
   * $str at this points seems like
   * Array(
   *  [0] => Array(
   *    [0] => SKU
   *    [1] => sku_here
   *  )
   *  [1] => Array(
   *    [0] => Role
   *    [1] => role_name_here
   *  )
   *  [2] => Array(
   *    [0] => Expiration
   *    [1] => 1 year(s)
   *   )
   *  [3] => Array(
   *    [0] => Shippable
   *    [1] => No
   *  )
   *  [4] => Array(
   *    [0] => Multiply by quantity
   *    [1] => No
   *  )
   * )
   */
 
$rid = uc_myca_get_role_rid($str[1][1]); //the rid of the role to be renewed
 
$extra_roles = array('administrators');  //should be defined as drupal variable in db
 
$sql = "DELETE FROM {users_roles} WHERE uid='{$account->uid}' AND rid != '{$rid}' AND ";
  foreach(
$extra_roles as $role){
   
$role_id = uc_myca_get_role_rid($role);
   
$sql .= "rid != '{$role_id}' AND";
  }
 
$sql = substr($sql,0,strlen($sql)-4); //remove the last "AND " from $sql query
 
db_query($sql); //delete record from users_roles
 
db_query("DELETE FROM {uc_roles_expirations} WHERE uid='%d' AND rid != '%d'",$account->uid,$rid); //delete record from ubercart's role expirations
}

/*
* This function gets a role id
* and turns it into the equivalent
* role name.
*/
function uc_myca_get_role_name($rid){
 
$roles = db_fetch_array(db_query("SELECT name FROM {role} WHERE rid='%d'",$rid));
  return
$roles['name'];
}

/*
* This function gets a role name
* and turns it into the equivalent
* role id
*/
function uc_myca_get_role_rid($name){
 
$roles = db_fetch_array(db_query("SELECT rid FROM {role} WHERE UPPER(name)=UPPER('%s')",$name));
  return
$roles['rid'];
}
?>
AttachmentSize
uc_myca.module 5.2 KB
wyattbiker's picture
Offline
Joined: 09/25/2010
Juice: 18
Re: Rewrite uc_myca_action_order_delete(): Multiple roles suppor

Would you have a description how to install the uc_myca.module module?

Thanks

vensires's picture
Offline
Joined: 07/30/2010
Juice: 65
Re: Re: Rewrite uc_myca_action_order_delete(): Multiple roles su

Use the code below in a uc_myca.info file

; $Id: uc_myca.info,v 1.0 2010/11/01 14:55:53 vensires Exp $
name = MyConditionalActions
description = ConditionalActions for deleting previous roles when buing new
package = "Ubercart - extra"
core = 6.x
php = 5.0
dependencies[] = uc_product

Copy both files in the same folder named uc_myca under your modules folder (usually sites/all/modules) and go to admin/store/ca/overview. There you will have to change the weight of the Grant or renew purchased roles. Grant or renew purchased roles must get effect AFTER the uc_myca gets effect. Eg. if Grant or renew purchased roles is 2, then uc_myca must be 1 or 0 and NOT 2 or 3 or more.

Also pay attention where I have written in the module this line:

$extra_roles = array('administrators');  //should be defined as drupal variable in db

This array must be filled with your extra roles(if any) in the drupal system that have nothing to do with the subscriptions. For example, you may have administrators, managers, forum-managers plus roles obtained with a subscription fee (like Bronze, Silver, Gold). If this is the case, then the extra_roles variable must be like this

$extra_roles = array('administrators','managers','forum-managers');
vensires's picture
Offline
Joined: 07/30/2010
Juice: 65
Re: need to remove role on purchase

I created a cleaner version of uc_myca with an admin panel and it works perfectly. For me at least. Could you all please test it? I remind you that the CA "Delete all roles except authenticated" created by this module, must be lighter than "Grant or renew purchased roles".

AttachmentSize
uc_myca.zip 2.2 KB
vensires's picture
Offline
Joined: 07/30/2010
Juice: 65
UC Clear Roles

I also created a project(sandboxed at the moment) with the module I created above. Its name is UC Clear Roles and can be found here in order to become a full project.