variable_get(USERPOINTS_TRANS_UCPOINTS, 'Points'), '!points' => variable_get(USERPOINTS_TRANS_LCPOINTS, 'points'), '!point' => variable_get(USERPOINTS_TRANS_LCPOINT, 'point') ); } return $trans; } function userpoints_txn_status() { return array( USERPOINTS_TXN_STATUS_APPROVED => t('Approved'), USERPOINTS_TXN_STATUS_PENDING => t('Pending'), USERPOINTS_TXN_STATUS_DECLINED => t('Declined'), ); } /** * Implementation of hook_help(). */ function userpoints_help($section) { switch ($section) { case 'admin/settings/userpoints': $output = t('Configure userpoints moderation and branding translation', userpoints_translation()); break; case 'admin/help#userpoints': $output = t('Users earn !points as they post nodes, comments, and vote on nodes', userpoints_translation()); } return $output; } /** * Implementation of hook_menu(). */ function userpoints_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'path' => 'userpoints', 'callback' => 'userpoints_list_users', 'title' => t('users by !points', userpoints_translation()), 'description' => t('List users by !points', userpoints_translation()), 'access' => user_access(USERPOINTS_PERM_VIEW), 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/userpoints', 'callback' => 'drupal_get_form', 'callback arguments' => array('userpoints_admin_settings'), 'title' => t('!Points settings', userpoints_translation()), 'description' => t('Configure userpoints settings'), 'access' => user_access(USERPOINTS_PERM_ADMIN), 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/user/userpoints', 'callback' => 'userpoints_admin_manage', 'title' => t('!Points', userpoints_translation()), 'description' => t('Manage !points', userpoints_translation()), 'access' => user_access(USERPOINTS_PERM_ADMIN), ); $items[] = array( 'path' => 'admin/user/userpoints/manage', 'callback' => 'userpoints_admin_manage', 'title' => t('Manage'), 'access' => user_access(USERPOINTS_PERM_ADMIN), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -1, ); $items[] = array( 'path' => 'admin/user/userpoints/add', 'callback' => 'drupal_get_form', 'callback arguments' => array('userpoints_admin_txn'), 'title' => t('Add'), 'description' => t('Admin add/delete userpoints'), 'access' => user_access(USERPOINTS_PERM_ADMIN), 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/user/userpoints/edit', 'callback' => 'drupal_get_form', 'callback arguments' => array('userpoints_admin_txn'), 'access' => user_access(USERPOINTS_PERM_ADMIN), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/user/userpoints/approve', 'callback' => 'userpoints_admin_approve', 'access' => user_access(USERPOINTS_PERM_ADMIN), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/user/userpoints/decline', 'callback' => 'userpoints_admin_approve', 'access' => user_access(USERPOINTS_PERM_ADMIN), 'type' => MENU_CALLBACK, ); } return $items; } /** * Implementation of hook_perm(). */ function userpoints_perm() { return array (USERPOINTS_PERM_VIEW, USERPOINTS_PERM_USE, USERPOINTS_PERM_ADMIN); } /** * menu callback for settings form. */ function userpoints_admin_settings() { $form['status'] = array( '#type' => 'fieldset', '#title' => t('Moderation'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -1, ); $form['status'][USERPOINTS_POINTS_MODERATION] = array( '#type' => 'radios', '#title' => t('Transaction status'), '#default_value' => variable_get(USERPOINTS_POINTS_MODERATION, 0), '#options' => array(t('Approved'), t('Moderated')), '#description' => t('Select whether all !points should be approved automatically, or moderated, and require admin approval', userpoints_translation()), ); $group = 'renaming'; $form[$group] = array( '#type' => 'fieldset', '#collapsible' => TRUE, '#collapsed' => TRUE, '#title' => t('Points branding'), ); $form[$group][USERPOINTS_TRANS_UCPOINTS] = array( '#type' => 'textfield', '#title' => t('Word to use in the interface for the upper case plural word !Points', userpoints_translation()), '#default_value' => variable_get(USERPOINTS_TRANS_UCPOINTS, 'Points'), '#size' => 20, '#maxlength' => 20, ); $form[$group][USERPOINTS_TRANS_LCPOINTS] = array( '#type' => 'textfield', '#title' => t('Word to use in the interface for the lower case plural word !points', userpoints_translation()), '#default_value' => variable_get(USERPOINTS_TRANS_LCPOINTS, 'points'), '#size' => 20, '#maxlength' => 20, ); $form[$group][USERPOINTS_TRANS_LCPOINT] = array( '#type' => 'textfield', '#title' => t('Word to use in the interface for the lower case singular word !point', userpoints_translation()), '#default_value' => variable_get(USERPOINTS_TRANS_LCPOINT, 'point'), '#size' => 20, '#maxlength' => 20, ); $form['setting'] = module_invoke_all('userpoints', 'setting'); return system_settings_form($form); } /** * @param uid: user id of the user to get or lose the points * * @return number of current points in that user's account */ function userpoints_get_current_points($uid = 0) { return (int)db_result(db_query('SELECT points FROM {userpoints} WHERE uid = %d', $uid)); } /** * @param op: operation to be performed. * 'points' * modules should use this to award points * 'points before' * hook that fires before points are added * 'points after' * hook that fires after points have been added * @param points: number of points to add (if positive) or subtract (if negative) * @param uid: user id of the user to get or lose the points * @param event: optional event ID * @param description: optional description * @param reference: optional reference information, indexed * * @return FALSE when no action is take, TRUE when points are credited or debited */ function userpoints_userpointsapi($op, $points = 0, $uid = 0, $event = NULL, $description = NULL, $reference = NULL) { // anonymous users do not get points, and there have to be points to process if ($uid == 0 || $points == 0) { return FALSE; } // When called explicitly, we handle only three cases. The rest are hooks // that should be defined in other modules. if($op != 'points' && $op != 'txn approve' && $op != 'points approved'){ return FALSE; } // Load the user $user = user_load(array('uid'=>$uid)); // Call the _userpoints hook, and stop if one of them returns FALSE // This will be handy later $rc = module_invoke_all('userpoints', 'points before', $points, $uid, $event); foreach($rc as $key => $value) { if ($value == FALSE) { // Do not process the points return FALSE; } } if ($points < 0) { $msg = t('lost'); } else { $msg = t('earned'); } // If $op is 'points', then the points MAY or MAYBE NOT subject to // approval, depending on user settings. If they are, then // write the transaction (with the noderation flag on) and return - which // will provent the rest of the function from actually assigning the // points if ($op == 'points') { $moderation = variable_get(USERPOINTS_POINTS_MODERATION, FALSE); userpoints_transaction($moderation, $points, $uid, $event, $description, $reference); // If points are being moderated, then write a message to the user and // that's it! if ($moderation) { // Points are moderated, so we do nothing for now. drupal_set_message(t('User %uname %op %pointsvalue !points, pending administrator approval.', array_merge(userpoints_translation(), array( '%uname' => $user->name, '%op' => $msg, '%pointsvalue' => abs($points), '%total' => $current_points) ))); return TRUE; } } // If the points are pre-approved, then just write the trail if ($op == 'points approved') { userpoints_transaction(FALSE, $points, $uid, $event, $description, $reference); } // *********************** // At this point, regardless of what $op is, the module needs to // actually award the points. (Keep in mind that if $op was 'point' and // moderation was on, then it won't get to this part). // *********************** // Calculate the current point $current_points = (int)$points + userpoints_get_current_points($uid); // Check if user has earned points if ($points > 0) { // Set the max_points to be the current max points, plus whatever earned in this transaction $max_points = db_result(db_query('SELECT max_points FROM {userpoints} WHERE uid = %d', $uid)); $max_points = $current_points + (int)$max_points; } drupal_set_message(t('User %uname %op %pointsvalue !points! Total now is %total points.', array_merge(userpoints_translation(), array( '%uname' => $user->name, '%op' => $msg, '%pointsvalue' => abs($points), '%total' => $current_points) ))); if (_userpoints_user_exists($uid)) { db_query("UPDATE {userpoints} SET points = %d, max_points = %d, last_update = %d WHERE uid = %d", $current_points, $max_points, time(), $uid); } else { $result = db_query("INSERT INTO {userpoints} VALUES (%d, %d, %d, %d)", $uid, $current_points, $max_points, time()); } module_invoke_all('userpoints', 'points after', $points, $uid, $event); return TRUE; } function userpoints_transaction($moderation, $points = 0, $uid = 0, $event = NULL, $description = NULL, $reference=NULL) { db_query("INSERT INTO {userpoints_txn} VALUES (0, %d, 0, %d, %d, %d, '%s', '%s', '%s')", $uid, $points, time(), $moderation, $event, $description, $reference); return $moderation; } function _userpoints_user_exists($uid) { return (int)db_result(db_query('SELECT COUNT(*) FROM {userpoints} WHERE uid = %d', $uid)); } function userpoints_user($op, &$edit, &$account, $category = '') { switch($op) { case 'delete': // The user is being deleted, delete all traces in userpoints and txn tables db_query('DELETE FROM {userpoints} WHERE uid = %d', $account->uid); db_query('DELETE FROM {userpoints_txn} WHERE uid = %d', $account->uid); break; case 'view': // Get the points for the user $points = userpoints_get_current_points($account->uid); if (user_access(USERPOINTS_PERM_ADMIN)) { $points = l($points, 'admin/user/userpoints/add/'. $account->uid, array('title' => t('Manage points'))); } $disp_points[] = array( 'title' => t('User !points', userpoints_translation()), 'value' => $points, ); return array(t('!Points', userpoints_translation()) => $disp_points); break; } } function userpoints_admin_manage() { $header = array( array('data' => t('User'), 'field' => 'uid', 'sort' => 'desc'), array('data' => t('Time stamp'), 'field' => 'time_stamp'), array('data' => t('!Points', userpoints_translation()), 'field' => 'points'), array('data' => t('Event'), 'field' => 'event'), array('data' => t('Operation', userpoints_translation())), ); $sql = "SELECT t.txn_id, t.uid, t.time_stamp, t.points, t.event, t.status FROM {userpoints_txn} t WHERE t.status = %d"; $sql .= tablesort_sql($header); $result = pager_query($sql, USERPOINTS_PAGE_COUNT, 0, NULL, USERPOINTS_TXN_STATUS_PENDING); while ($data = db_fetch_object($result)) { $user = user_load(array('uid'=>$data->uid)); $rows[] = array( array('data' => theme('username', $user)), array('data' => format_date($data->time_stamp, 'custom', 'Y-m-d H:i')), array('data' => $data->points, 'align' => 'right'), array('data' => $data->event), array('data' => l('approve', "admin/user/userpoints/approve/$data->txn_id") . ' ' . l('decline', "admin/user/userpoints/decline/$data->txn_id") . ' ' . l('edit', "admin/user/userpoints/edit/$data->txn_id") ), ); } $output = theme('table', $header, $rows); $output .= theme('pager', NULL, 30, 0); return $output; } function userpoints_admin_approve() { global $user; $op = arg(3); $txn_id = (int)arg(4); if ($txn_id) { switch($op) { case 'approve': $result = db_query("SELECT uid, event, points, description, reference FROM {userpoints_txn} WHERE status = %d AND txn_id = %d", USERPOINTS_TXN_STATUS_PENDING, $txn_id); $data = db_fetch_object($result); drupal_set_message(t('Transaction approved')); // This transaction has not been credited to the user's account, so credit it first userpoints_userpointsapi('txn approve', $data->points, $data->uid, $data->event, $data->description, $data->reference); // Set it to approved db_query("UPDATE {userpoints_txn} SET status = %d, approver_uid = %d WHERE txn_id = %d", USERPOINTS_TXN_STATUS_APPROVED, $user->uid, $txn_id); break; case 'decline': db_query("UPDATE {userpoints_txn} SET status = %d, approver_uid = %d WHERE txn_id = %d", USERPOINTS_TXN_STATUS_DECLINED, $user->uid, $txn_id); drupal_set_message(t('Transaction declined')); break; } } drupal_goto('admin/user/userpoints'); } function userpoints_admin_txn() { global $user; $mode = arg(3); $txn_id = (int)arg(4); if ($txn_id) { $txn_user = user_load(array('uid' => $txn_id)); } $timestamp = format_date(time(), 'custom', 'Y-m-d H:i O'); if ($mode == 'edit' && $txn_id) { $result = db_query('SELECT * FROM {userpoints_txn} WHERE txn_id = %d', $txn_id); $txn = db_fetch_object($result); $timestamp = format_date($txn->time_stamp, 'custom', 'Y-m-d H:i O'); } $form['txn_user'] = array( '#type' => 'textfield', '#title' => t('User Name'), '#size' => 30, '#maxlength' => 60, '#default_value' => $txn_user->name, '#autocomplete_path' => 'user/autocomplete', '#description' => t('Drupal User ID for the user you want the points to affect'), ); $form['points'] = array( '#type' => 'textfield', '#title' => t('Points'), '#size' => 10, '#maxlength' => 10, '#default_value' => $txn->points, '#description' => t('Number of points to add/subtract from the user. For example, 25 (to add points) or -25 (to subtract points).'), ); $form['time_stamp'] = array( '#type' => 'textfield', '#title' => t('Date/Time'), '#default_value' => $timestamp, '#size' => 30, '#maxlength' => 30, '#description' => t('Date and time of this transaction, in the form YYYY-MM-DD HH:MM +ZZZZ'), ); $form['description'] = array( '#type' => 'textarea', '#title' => t('Description'), '#default_value' => $txn->description, '#width' => 70, '#lines' => 5, '#description' => t('Enter an optional description for this transaction, such as the reason it is created.'), ); $form['reference'] = array( '#type' => 'textfield', '#title' => t('Reference'), '#default_value' => $txn->reference, '#size' => 30, '#maxlength' => 128, '#description' => t('Enter optional reference for this transaction. This field will be indexed and searchable.'), ); switch($mode) { case 'add': $form['approver_uid'] = array( '#type' => 'hidden', '#value' => $user->uid, ); $form['event'] = array( '#type' => 'hidden', '#value' => 'admin', ); $form['status'] = array( '#type' => 'hidden', '#value' => USERPOINTS_TXN_STATUS_PENDING, ); $form['mode'] = array( '#type' => 'hidden', '#value' => $mode, ); break; case 'edit': $form['txn_user'] = array( '#type' => 'hidden', '#value' => $txn_user, ); $form['approver_uid'] = array( '#type' => 'textfield', '#description' => t('Approver ID'), '#default_value' => $txn->approver_uid, '#size' => 10, '#maxlength' => 7, '#description' => t('The user ID of the person who approved this transaction. 0 means not yet approved.'), ); $form['event'] = array( '#type' => 'textfield', '#description' => t('Event'), '#default_value' => $txn->event, '#size' => 20, '#maxlength' => 20, '#description' => t('The event type for this transaction. Normally, it is "admin".'), ); $form['status'] = array( '#title' => t('Approval status'), '#type' => 'radios', '#options' => userpoints_txn_status(), '#description' => t('Approval status of the transaction.'), '#default_value' => $txn->status, ); break; } $form['mode'] = array( '#type' => 'hidden', '#default_value' => $mode ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return $form; } function userpoints_admin_txn_submit($form_id, $form = NULL) { if ($form_id != 'userpoints_admin_txn') { return; } $txn_user = user_load(array('name' => $form['txn_user'])); switch($form['mode']) { case 'add': userpoints_userpointsapi('points', $form['points'], $form['uid'], 'admin', $form['description'], $form['reference']); break; case 'edit': db_query("UPDATE {userpoints_txn} SET uid = %d, approver_uid = %d, points = %d, time_stamp = %d, event = '%s', description = '%s', reference = '%s', status = %d WHERE txn_id = %d", $form['uid'], $form['approver_uid'], $form['points'], strtotime($form['time_stamp']), $form['event'], $form['description'], $form['reference'], $form['status'], $form['txn_id']); drupal_set_message(t('Transaction has been updated.')); } drupal_goto('admin/user/userpoints'); } function userpoints_list_users() { $sql = "SELECT p.uid, u.name, p.points FROM {userpoints} p INNER JOIN {users} u USING (uid)"; $sql_cnt = "SELECT COUNT(DISTINCT(uid)) FROM {userpoints}"; $header = array( array('data' => t('User'), 'field' => 'u.name'), array('data' => t('!Points', userpoints_translation()), 'field' => 'p.points', 'sort' => 'desc'), ); $sql .= tablesort_sql($header); $result = pager_query($sql, 30, 0, $sql_cnt); while ($data = db_fetch_object($result)) { $rows[] = array( array('data' => theme('username', $data)), array('data' => $data->points, 'align' => 'right'), ); } $output = theme('table', $header, $rows); $output .= theme('pager', NULL, 30, 0); return $output; } function userpoints_block($op = 'list', $delta = 0, $edit = array()) { global $user; $num = 5; switch ($op) { case 'list': $blocks[0]['info'] = t('User\'s !points', userpoints_translation()); $blocks[1]['info'] = t('Highest Users'); return $blocks; case 'view': if (user_access(USERPOINTS_PERM_VIEW)) { switch ($delta) { case 0: $title = t('@user\'s !points', array_merge(array('@user' => $user->name), userpoints_translation()));; if ($user->uid) { $points = (int) db_result(db_query('SELECT points FROM {userpoints} WHERE uid = %d', $user->uid)); $show_points = format_plural($points, t('!point', userpoints_translation()), t('!points', userpoints_translation())); $content = t('You have %p %c', array('%p' => $points, '%c' => $show_points)); } else { $content = t('!Points are visible to logged in users only',userpoints_translation()); } break; case 1: $title = t('Highest Users'); $result = db_query_range('SELECT p.uid, u.name, p.points FROM {userpoints} p INNER JOIN {users} u USING (uid) ORDER BY p.points DESC', 0, $num); while ($data = db_fetch_object($result)) { $rows[] = array( array('data' => theme('username', $data)), array('data' => $data->points, 'align' => 'right')); } $header = array(t('User'), t('!Points', userpoints_translation())); $content = theme('table', $header, $rows); $content .= '