Hiya.. here is a rough rewrite to the userpoints_basic for those of you who wanted the userpoints ONLY to be assigned to the user after their node has been moderated.

STEP 1:
create a new table first

CREATE TABLE `userpoints_pending_moderation` (
  `nid` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

STEP 2:
replace the nodeapi function inside the userpoints_basic module

function userpoints_nodeapi(&$node, $op, $teaser, $page) {
  static $orig_uid;
  $points = variable_get(USERPOINTS_POST . $node->type, 0);
  switch($op) {
    case 'insert':
      $points = $points;
      // check if the node is already moderated, if so give points to user
      if ($node->moderate == 0 ) {
        userpoints_userpointsapi('points',$points, $node->uid, $node->type);
      }
      // the node needs to moderated, add points to temp table
      else {
        db_query('INSERT INTO {userpoints_pending_moderation} nid VALUES %d', $node->nid);
      }
      break;
    case 'delete':
      $points = -$points;
      userpoints_userpointsapi('points',$points, $node->uid, $node->type);
      break;
    case 'prepare':
      $orig_uid = $node->uid;
      break;
    case 'update':
      if ($node->uid != $orig_uid) {
        // Add to the new node owner
        userpoints_userpointsapi('points',$points, $node->uid, $node->type);

        // subtract from the original node owner
        $points = -$points;
        userpoints_userpointsapi('points',$points, $orig_uid, $node->type);
      }
      break;
    case 'view':
      if ($page == 1 and $node->moderate == 0 ) {
        $nid = db_result(db_query('SELECT nid from {userpoints_pending_moderation} where nid=%d', $node->nid));
        if($nid){
          $points = $points;
          userpoints_userpointsapi('points',$points, $node->uid, $node->type);
          db_query('DELETE FROM {userpoints_pending_moderation} WHERE nid=%d', $node->nid);
        }
      }
      break;
  }
}

To do:
Find a better way to identify when a node->moderate staus is updated from 1 to 0. Currently this is an additional hit on the database when the view op is loaded. I am using the modr8 module which does not use nodeapi hook to update the staus. The above will work, it just takes 1 extra hit on the db.

Anyone got any way/ideas to improve this code?

Comments

dakku’s picture

a slightly updated version

function userpoints_nodeapi(&$node, $op, $teaser, $page) {
  static $orig_uid;
  $points = variable_get(USERPOINTS_POST . $node->type, 0);
  switch($op) {
    case 'insert':
      $points = $points;
      // check if the node is already moderated, if so give points to user
      if ($node->moderate == 0 ) {
        userpoints_userpointsapi('points',$points, $node->uid, $node->type);
      }
      // the node needs to moderated, add points to temp table
      else {
        db_query('INSERT INTO {userpoints_pending_moderation} nid VALUES %d', $node->nid);
      }
      break;
    case 'delete':   
      // subtract only if the node got moderated and user actually received points
      if ($node->moderate == 0 ) {
        $points = -$points;
        userpoints_userpointsapi('points',$points, $node->uid, $node->type);
      }
      break;
    case 'prepare':
      $orig_uid = $node->uid;
      break;
    case 'update':
      if ($node->uid != $orig_uid) {
        // Add to the new node owner
        userpoints_userpointsapi('points',$points, $node->uid, $node->type);

        // subtract from the original node owner
        $points = -$points;
        userpoints_userpointsapi('points',$points, $orig_uid, $node->type);
      }
      break;
    case 'view':
      // try to eliminate the number of queries to mysql. 
      // update the userpoints on the view hook. 
      //allows for modules like modr8 to do their bit
      if ($page == 1 and $node->moderate == 0 ) {
        // check if there is any points waiting to be added
        $nid = db_result(db_query('SELECT nid from {userpoints_pending_moderation} where nid=%d', $node->nid));
        if($nid){
          // great stuff, lets add the points, 
          //someone somewhere didnt use the update hook to change moderate status
          $points = $points;
          userpoints_userpointsapi('points',$points, $node->uid, $node->type);
          // delete entry from temp table
          db_query('DELETE FROM {userpoints_pending_moderation} WHERE nid=%d', $node->nid);
        }
      }
      break;
  }
}

Updated the delete op to deduct points for nodes that had been approved.

deciphered’s picture

Hi dakku,

Firstly I have to say great work on this modification, it's definetely a necessary change.

I did however need to make a slight modification to the SQL query so that it would work, changing the following line:
db_query('INSERT INTO {userpoints_pending_moderation} nid VALUES %d', $node->nid);
to:
db_query('INSERT INTO {userpoints_pending_moderation} (nid) VALUES (%d)', $node->nid);

Also, while testing I noticed that if I approved a node in the moderation queue then logged out and browsed to the node that I would (as an anonymous user) get the notification that the user had recieved X ammount of points. To an anonymous user visiting the site this would be confusing and something that I would wish no to happen. I understand that it happens due to the points being delayed till the view hook is called, however I would personally like to change it so that the points are assigned as soon as I moderate said node. Can you supply any information on how I could do so?

jredding’s picture

Can you explain why you need the additional table? I'm a little confused as to why you can't simply move the points approval over to the update status? If this because you can't track if points have been awarded for a particular node? (i.e. multiple points awarded each time a node is updated).

Why not add the points into the user points and force moderation on the points? Then when the node moves out of moderation the points also move out of moderation. No additional tables needed and it could be a quick and easy patch to the existing module.

Thoughts? Comments?

btw: I think your code in its current state would leave straggling entries in the DB.
Example:
If a node is inserted and then put into moderation an entry is made to the userpoints_pending_moderation table. If that node is then deleted BEFORE it has been moderated the entry would be left behind (i.e. there is no check on the delete $op to remove straggling entries)

finally submitting a Patch is better than posting code in the comments.

jredding’s picture

Priority: Normal » Minor
Status: Needs review » Needs work

changing status as a better patch could be created. This one will leave straggling entries in the DB and I'm not sure if this is the best way to handle the situation.

jredding’s picture

Status: Needs work » Closed (won't fix)

Changing status to "won't fix" as the new database structure in version 3.x negate the need for a secondary table and the code above should be reworked so that it doesn't leave straggling entries in the DB.

nainainai’s picture

anyone still working on this one?

neofpo’s picture

Hello,

I've been working at a way to give points on node promotion / no promotion status (similar case as this topic).

I am stuck at the same point as you guys: there is no way to know some publishing flag state before the update itself. A hook at the 'prepare' operation won't solve, since it may not be used by some modules (such as fasttoggle).

Creating a new table to store all the flags, does part of the deal. However, there is no way to know a flag's state if it was not inserted before at the table. It would require to upon module being enabled, this table be filled with flags for each and every existing node, not quite a good solution though.

I am kind of new to Drupal development, but wouldn't it be better if Drupal's hook_nodeapi() gave some information regarding those publishing flags state, before the update, at the 'update' action? Something like a $node->promote_old style variables. Perhaps to a future release, then User Points could use it for a better solution.

I found a lot of people here and there at Drupal.org asking for similar features, all of which could be solved if this so called API I told above existed.

Anyone has any idea on how to get this API upgrade to happen? Or have a better solution?

Bye.

neofpo’s picture

Please reffer to this comment as a patch has been released.

FireBoss’s picture

I needed to be able to award points when nodes were published/unpublished and not when they were posted by the user.
I accomplished this for my site today by changing a function within userpoints_nc module.
I wasn't able to find a good, bug free solution anywhere so I made my own.
It has tested quite well and doesn't have the common problems other solutions and the above mentioned patch suffer from.

This post has the code:

http://drupal.org/node/416358