Grant points to all comment authors upon tagging the node
Good content brings good comments with it, and good comments improve the post they are related to, so in a site where users are rewarded for their ideas and contribution, it is just a matter of fairness to let the commenters of a good post to be rewarded as well.
In our ideas management system, we want to grant points to each comment author when the post is tagged with a specific term. So far this is impossible with rules.module .
In our example, we'll try to grant 1 point when the post is tagged as “Under review”, and 2 points when the post is tagged as “Launched”.
One more requirement is to keep it exposed to the administrator through the rules UI, so she will be able to grant more or less points, add or change tags or even switch to flags instead of terms (or any other condition or action).
**Few words on rules sets:**
A "rules set" is a group of rules with no trigger (event).
When creating a rules set you can select the arguments which will be passed to the set once it is invoked. In our case we will need to identify the user to grant points to, and the content (node) to check for the specific term. To fire a rules set we can invoke it through code like in our case or from a triggered rule.
First we’ll create a rules set and name it “points to comments authors”. Now lets add two arguments:
1. User
2. Content
*Figure 1 - Rules set arguments settings (Don’t forget to tag your rule sets and your rules to make them available for exporting with features).*
Then we’ll add two rules under it named as:
- Under review comment author points
- Launched comment author points
Now lets set the first rule. As a condition we’ll select “content has term” which is a custom rule condition that we added. Create a file in your module folder named MODULENAME.rules.inc and add those lines:
<?php /**
* Implements hook_rules_condition_info().
*/
function MODLENAME_rules_condition_info() {
return array(
'rules_condition_content_has_term' => array(
'label' => t('Content has term'),
'arguments' => array(
'node' => array('type' => 'node', 'label' => t('Content')),
),
'help' => t('Check whether a node has a specified term.'),
'module' => 'MODLENAME',
),
);
}
/**
* Condition Implementation: Check if term exists on node.
*/
function rules_condition_content_has_term($node, $settings) {
if (!is_numeric($settings['term'])) {
$terms = taxonomy_get_term_by_name($settings['term']);
foreach ($terms as $tr) {
foreach ($node->taxonomy as $term) {
if (is_numeric($term)) {
$term = taxonomy_get_term($term);
}
if ($term->tid == $tr->tid) {
return TRUE;
}
}
}
}
foreach ($node->taxonomy as $term) {
if (is_numeric($term)) {
$term = taxonomy_get_term($term);
}
if ($term->tid == $settings['term']) {
return TRUE;
}
}
return FALSE;
}
?>
and another file named MODULENAME.rules_forms.inc with those lines:
<?php /**
* Form for input term ID or term name.
* @param $settings.
* @param $form.
* @param $form_state.
*/
function rules_condition_content_has_term_form($settings, &$form, $form_state) {
$form['settings']['term'] = array(
'#type' => 'textfield',
'#title' => t('Term ID or Term name'),
'#default_value' => !empty($settings['term']) ? $settings['term'] : '',
'#description' => t("Provide a term ID (tid) or a term name matching text (case is ignore)."),
'#required' => TRUE,
);
}
?>
Here is how it looks like in rules UI:
*Figure 2 - Adding the tag condition*
And as action we’ll select “Grant points to a user”. Set the number of points to 1.
We’ll repeat those steps for “launched” rule, when term name will be “launched” and the number of points will be 2.
That's it for rules settings, now we’ll invoke this rules set from our module:
<?php /**
* Implementation of hook_nodeapi().
*/
function MODULENAME_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch ($op) {
case 'presave':
//get the comments author on this node.
$resource = db_query("SELECT uid FROM {comments} WHERE nid = %d", $node->nid);
//Go over the comments authors and send them to the rule set to grant them points.
while($row = db_fetch_array( $resource )) {
$comment_author = user_load($row['uid']);
rules_invoke_rule_set('rules_points_to_comments_authors', array('user' => $comment_author, 'node' => $node));
}
break;
};
}
?>
This code will be invoked on each node save, with each user (comment author) passed as first argument and the node as a second one. Each rule will check the node for the term and if it exists, the user will be granted points according to whatever is specified in the rules set.
this code can be improved a bit, especially in the trigger part, but you get the idea... :)
**Dependencies:**
Core: Drupal 6.x
Contrib: Userpoints 1.x, Rules 1.x