Posted by jefgodesky on March 29, 2011 at 11:22pm
16 followers
Jump to:
| Project: | User Points |
| Version: | 7.x-1.x-dev |
| Component: | Code: userpoints_rules |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
Issue Summary
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.
| Attachment | Size | Status | Test result | Operations |
|---|---|---|---|---|
| rules_conditions.patch | 3.16 KB | Ignored: Check issue status. | None | None |
Comments
#1
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
#2
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.
#3
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.
#4
#5
Berdir, is there anything you want me to test with the supplied patch or are you going to take a stab at this?
--Ben
#6
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.
#7
Patch seems to being working for me. Thanks!
#8
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.
#9
Perhaps we should ask Fago and Klausi then. :)
#10
>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.
#11
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?
#12
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.
#13
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.
#14
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?
#15
I think with the original patch, you should be able to just select all of your categories, no?
#16
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.
#17
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!
#18
#19
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.
#20
Let's keep this open for now, would like to see a simpler solution...
#21
The brief time this had "fixed" status, it does not seem that anything was committed to the dev-branch at all?
#22
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.