According to the documentation, the User Points Rules integration used to have a number of conditions, but I don't see any of them in the beta release for Drupal 7.

The attached patch includes some functions to implement a condition that will check how many points a user has. It can be limited to a particular category, and compared to a threshold to assess equal, less than, less than or equal to, greater than, or greater than or equal to.

There's plenty of room for improvement on this, I'm sure, but I thought my contribution might help.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

BenK’s picture

Hmmm... I believe you can use Userpoints conditions in the existing module by using the default "Data comparison" condition supplied by Rules (and then using a data selector for the Userpoints item you want to compare).

Does the patch add any functionality beyond this?

--Ben

jefgodesky’s picture

No, the patch only adds a condition to allow you to compare the number of points a user has, potentially limited to points in a particular category.

I don't see anything about user points under the data selector for "Data comparison" on a Rules condition, though.

Berdir’s picture

Version: 7.x-1.0-beta1 » 7.x-1.x-dev

We already expose the points of a user with tokens, maybe we can expose it as entity properties too, so that it is accessible to rules.module.

Taxoman’s picture

Category: task » feature
BenK’s picture

Berdir, is there anything you want me to test with the supplied patch or are you going to take a stab at this?

--Ben

xanderol’s picture

I'm not sure if this is still being looked into or not but I gave the patch a try and it seems to work fine. Although it would be nice to have access to the totals and not just the individual categories. This becomes difficult if I want to keep my points based on node creation and comment creation separate and then promote someone to a role based on the total of the two.

It is possible to create three separate categories. One for comment points, one for node points and one for total points. Then go to the content type and set the points for content to the node category and the points for comments to the comment category. Then you have to create rules to increment or decrease the total category when either nodes or comments are created or deleted. Now just hide the total all categories in point settings. This allows you to keep the node and comment points in separate categories and the total category will be equal to the two combined. This is definitely not optimal but it does work.

Anonymous’s picture

Patch seems to being working for me. Thanks!

Berdir’s picture

As already explained before, the idea is, instead of adding a custom condition, to expose the points of a user as entity properties, in hook_entity_property_info(). This allows to access them in any possible way, for example using the points amount in a private message which is sent to the user or whatever.

This is already done for tokens, but it is unfortunately not possible (yet?) to access tokens in a data comparison condition.

So either the points need to be exposed like we do it already for tokens (which also allows to get the total or a specific category) or rules needs to be extended to allow data comparisons of token values.

giorgio79’s picture

Title: Rules Conditions: Check when a user has a certain number of points » Allow data comparisons of token values
Project: User Points » Rules
Version: 7.x-1.x-dev » 7.x-2.x-dev
Component: Code: userpoints_rules » Rules Engine

Perhaps we should ask Fago and Klausi then. :)

fago’s picture

Status: Active » Closed (won't fix)

>This is already done for tokens, but it is unfortunately not possible (yet?) to access tokens in a data comparison condition.

It's not supposed to work that way. It's working with entity properties that are provided via hook_entity_property_info(). If you want to make data available to rules, use that hook or implement hook_rules_data_info() and provide property info there in case you have a non-entity data structure.

Berdir’s picture

Title: Allow data comparisons of token values » Rules Conditions: Check when a user has a certain number of points
Project: Rules » User Points
Version: 7.x-2.x-dev » 7.x-1.x-dev
Component: Rules Engine » Code: userpoints_rules
Status: Closed (won't fix) » Active

Taking this one back home then ;)

Not sure how to do this. The problem is that our tokens are relatively complex because points could be split up into different categories and you can access your current points and your all-time-max points (each with categories + all). We have done this using two additional token types. But I obviously don't want to create entities for this :)

Is there a way to provide nested properties?

ohthehugemanatee’s picture

This is a big hole in the functionality of userpoints. I understand the problem of implementation... but in the meantime, can we post a PHP snippet that could pull a given user's points value into a Rules data variable? That way people can run comparisons with only one extra step.

The best other solution I can think of is to create integer fields on the user profile for each type of point on your site, and set up a rule to automatically increment the values in these fields as points are added. Then you can do comparisons with the numbers in the fields rather than the points directly.

Of course, if you're going to do that, why are you even bothering with userpoints? Very frustrating.

FilipNest’s picture

Not ideal but if you install the User Points Contributed modules you can use "Load Points of a User" in the actions stage. Sadly this isn't in the conditions stage but with a PHP snippet such as that described at #1293016: User doesn't get the role when they have enough points you can do most of what you'd want to do.

xanderol’s picture

I was able to use the above patch to add a condition which compares the total points by deleting this portion of the patch

'tid' => array(
'label' => t('!Points category', userpoints_translation()),
'type' => 'integer',
'options list' => 'userpoints_rules_get_categories',
),

Which gets rid of the category list and then changing

$points = userpoints_get_current_points($params['user']->uid, $params['tid']);

to

$points = userpoints_get_current_points($params['user']->uid, 'all');

This allows me to set a condition which compares the total points earned. But because I deleted the options list I lose the ability to chose a single category. Since 'all' is not a category it is not included in the options list array. What would be the best way to add it to the array?

I could just add a PHP code condition and call

$points = userpoints_get_current_points([userpoints-transaction:user:uid], 'all');

from there and compare it to a value but I've read that because the PHP code is stored in the database it can be less secure and less efficient that way. Any opinions on the matter?

jefgodesky’s picture

I think with the original patch, you should be able to just select all of your categories, no?

xanderol’s picture

The patch provides a drop down list that allows you to select a single category.

The function that gets called is

userpoints_get_current_points($uid = NULL, $tid = NULL)

here are the comments provided for the function.

/**

* Get current points of a user.

*

* @param $uid

* User ID of the user to get or lose the points.

* @param $tid

* Term ID to get points for, or 'all'.

*

* @return

* Number of current points in that user's account.

*/

so as far as I can tell you can only request points from a single category or all of them but nothing in between.

So instead of passing the taxonomy id into the function you can pass 'all' which will give you the total points of all of the categories but since 'all' is not a category it does not get added to the drop down list which is created by calling the userpoints_rules_get_categories() function.

IWasBornToWin’s picture

Status: Fixed » Active

Solved! This took about 2 days. Would be wonderful if many of these modules came with instructions...oh well. Here is how I made it work.

Extending from comment #13 above; load user points--here's how.

Basically you have a parent rule which has an action to fire a component made up of rule sets (a few separate rules). Side note-If you're using the rules link module it already creates a component for you.

Parent rule
action: Components: My rule set

My rule set (a component)
- rule1-load user points of a user
- rule2-validate user points balance and display message(action:system) if fails*
- rule3-validate user points balance and continue if pass*
* these two rules can be in either order. one displays message when the other fails, or vice versa.

step 1: within rules, create a COMPONENT of type: rules set. Choose a datatype, label, and machine name (ie;node, node, node). Then save.
step 2. add a rule to the new rule set component. Add action: "load user points balance". Save rule.
step 3. add other rules and make sure each of these rules has an initial condition of filtering on specific content type (ie;node of type article) before adding conditions for user points. If you don't do this the metadata drop-down likely won't have other data you may need in order to compare user points balance to.

You now have loaded user points in the condition drop-down of your next rule. This should get you where you need to be. You can now create other rules(within this component rules set)--rule2, rule3, etc., and create conditions within those rules.

In the conditions drop down you will now see an available condition named, - rule1-load user points of a user, or whatever you named your first rule.

works like a charm!

IWasBornToWin’s picture

Status: Active » Fixed
IWasBornToWin’s picture

Status: Active » Fixed

In case there is confusion, when you're finished creating all your rule sets within the component, you then go back to your main rule and create the action to run the component.

Berdir’s picture

Status: Fixed » Active

Let's keep this open for now, would like to see a simpler solution...

Taxoman’s picture

The brief time this had "fixed" status, it does not seem that anything was committed to the dev-branch at all?
My goodness, scratch that, the brain must have been out to lunch or perhaps I did not read the "fix" description at all...

fehin’s picture

I recently created a rule that reacts on the event of a node being flagged. I wanted to check if user has enough points before removing points for flagging the node but the condition for this is missing in D7. I couldn't find any condition for points when reacting on flag event. Based on the tutorial here http://drupal.org/node/1389248 (step 5), it seems this was available in D6.

fehin’s picture

I used the patch in the original post and it worked perfectly. Thank you.

fonant’s picture

This is possible using a Rules Component to carry out the points comparison and actions, called by a rule that loads the userpoints value and then calls the component. But it's a bit of a workaround: would be much neater to have userpoint total comparisons in a rule's Conditions.

IWasBornToWin’s picture

You can have userpoints total in a condition but you must first do an action of loading user points. Then run a condition based on that loaded value.

makheda’s picture

that's not the right way to do it.
user is an entity, then userpoints should be added by 'hook entity properties info alter' so we could access all details by default rules operations.
That's made available by entity API module, already a dependency for userpoints rules integration

joshmmo’s picture

I am having an issue when I try and patch the file I get:

patching file `userpoints_rules.rules.inc'
Hunk #1 succeeded at 4 with fuzz 2 (offset -1 lines).
Hunk #2 succeeded at 75 with fuzz 1 (offset -216 lines).
Hunk #3 FAILED at 146.
1 out of 3 hunks FAILED -- saving rejects to userpoints_rules.rules.inc.rej

Here is the content of the file:

***************
*** 84,86 ****
  function userpoints_rules_get_current_points($account, $tid) {
    return array('loaded_points' => userpoints_get_current_points($account->uid, $tid));
  }
--- 146,161 ----
  function userpoints_rules_get_current_points($account, $tid) {
    return array('loaded_points' => userpoints_get_current_points($account->uid, $tid));
  }
+ 
+ /**
+  * Returns options for ways to compare a number to a number of points.
+  */
+ function userpoints_condition_get_comparisons() {
+   return array(
+     'lt' => t('Less than'),
+     'le' => t('Less than or equal to'),
+     'eq' => t('Equal to'),
+     'ge' => t('Greater than or equal to'),
+     'gt' => t('Greater than'),
+   );
+ }

I am on userpoints 7.x-1.0
I am not very git savvy so any help is appreciated.

joshmmo’s picture

For those who run into the same issue I had, I checked-out the 7.x-1.x version from git and applied the patch to that version and it worked just fine.

You can follow the steps here to switch to a different branch and how to apply a patch:
http://drupal.org/project/userpoints/git-instructions

dan.hu’s picture

same problem here. subscribed.

chefnelone’s picture

After I apply patch supplied in #1 I get removed the "User was awarded Sweetpoints" event.
Anyone with the same problem?

When applied the patch I got:

$ git apply -v rules_conditions.patch
rules_conditions.patch:9: trailing whitespace.
 
Checking patch userpoints_rules.rules.inc => userpoints_rules.rules.new.inc...
Hunk #1 succeeded at 4 (offset -1 lines).
Hunk #2 succeeded at 206 (offset -85 lines).
Hunk #3 succeeded at 277 (offset -85 lines).
Applied patch userpoints_rules.rules.inc => userpoints_rules.rules.new.inc cleanly.
warning: 1 line adds whitespace errors.
chefnelone’s picture

#Berdir: You said "We already expose the points of a user with tokens" Can you tell which one is the token? Can we use it in a Comparison condition ?

dalegrebey’s picture

For the life of me, I can not seem to get this to work after days of trying.

Thank you for the instructions, but not too sure if they are just not written clearly or if I am just dense this week.

dalegrebey’s picture

This is essentially what I am trying to achieve: When certain fields are checked (or not) when creating a node, increase the amount of user points it requires to publish that node, but before publishing, validate that the user has enough user points to publish that node based on the fields selected and if they do, publish it, if they do not, display an error message.

Has been brain swimming in all sorts of circles.

tahiticlic’s picture

Any clue on how to achieve this ?

Since many contributed modules don't work on D7, this is a critical issue to make use of points other than just displaying it...

[Solved] applying patch #1 on last 7.x-1.x git version does the trick :-)

gladiatorhl2’s picture

I have already tried 7.x-1.x-dev and I can't make it work. What is it supposed to do??? Does this function have to appear in Rules - Conditions - Add condition? Where do we have to see it? I am confused about component rule set described above which does not help either. There is NOT validate userpoints!

ufku’s picture

We were able to expose user points to rules data selector using a custom module

/**
 * Implements hook_entity_property_info().
 * Exposes user properties to rules data selector.
 */
function MYMODULE_entity_property_info() {
  $info = array();
  if (module_exists('userpoints')) {
    $info['user']['properties']['points'] = array(
      'label' => t('!Points', userpoints_translation()),
      'description' => t('The amount of !points this user has. If there are multiple categories, only the default category is taken into account.', userpoints_translation()),
      'getter callback' => 'MYMODULE_get_user_property',
      'type' => 'integer',
      'computed' => TRUE,
    );
  }
  return $info;
}

/**
 * Callback for getting user properties defined by MYMODULE_entity_property_info().
 */
function MYMODULE_get_user_property($account, $options, $name, $entity_type) {
  switch ($name) {
    case 'points':
      return module_invoke('userpoints', 'get_current_points', $account->uid);
  }
}

This will expose points in default category as site:current-user:points or user:points allowing it to be used in data comparison.

podarok’s picture

Issue summary: View changes
Status: Active » Needs review
pinkonomy’s picture

Any news on this?

pinkonomy’s picture

Patch from #1 doesn't work for me,tested with 7.x-1.x-dev
Opening again

pinkonomy’s picture

Status: Needs review » Needs work
Aracon’s picture

This is very useful functionality. Waiting for implementation.

pitxels’s picture

ufku thanks for the module in #36

nicodv’s picture

Thanks for the module in #36 :)

estoyausente’s picture

#39 I just reroll it. It seems that work perfectly. Anybody can test it a little bit more?

Thanks

estoyausente’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
estoyausente’s picture

Detect invalid PHP syntax? :S

I'm a genius

Leeteq’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
PlayfulWolf’s picture

-  ) + $params;
+  )  $params;

?

mscheid queued rules_conditions.patch for re-testing.

estoyausente’s picture

Not anymore dirty things ^^

luismagr’s picture

Status: Needs work » Needs review

Set the status to needs review to pass the tests

luismagr’s picture

I can't understand the reason for moving this comparison to an action. For me the first patch solves my problem and have more sense.

kimwes’s picture

The most recent patch was probably placed in the wrong hook(action hook instead of condition). So I took the first patch which was correct but dated and rerolled it. I also changed the category selection to support all categories. Works fine after testing.

karopka’s picture

patch is not working for last stable version

pinkonomy’s picture

Could anyone tell how to achieve this with a Rules Component?
thanks

pinkonomy’s picture

@IWasBornToWin
Regarding the comment #17,after creating the Rule set,I cannot see the condition: rule1-load user points of a user
on the rule.What am I missing?
Also can the rule be exported please?

EDIT:I finally found it.The condition should be on the Rule set as a Data comparison.Then the Rule set should be loaded to the main Rule as an action.Happy!

Albert Volkman’s picture

Status: Needs review » Reviewed & tested by the community

Works for me.

oturpin’s picture

Hi All

Is there any target official release for integrating this patch ?

Thx

gumanov’s picture

Any updates on this? Will it be added to the official release?

TheDukeofURL’s picture

Patch in #55 no longer works against latest dev.