You are here

userpoints.module in User Points 7.2

File

userpoints.module
View source
<?php

// Copyright 2005-2007 Khalid Baheyeldin http://2bits.com
define('USERPOINTS_TRANS_UCPOINTS', 'userpoints_trans_ucpoints');
define('USERPOINTS_TRANS_LCPOINTS', 'userpoints_trans_lcpoints');
define('USERPOINTS_TRANS_UCPOINT', 'userpoints_trans_ucpoint');
define('USERPOINTS_TRANS_LCPOINT', 'userpoints_trans_lcpoint');
define('USERPOINTS_TRANS_UNCAT', 'userpoints_trans_uncat');
define('USERPOINTS_STATUS', 'userpoints_status');
define('USERPOINTS_POINTS_MODERATION', 'userpoints_points_moderation');
define('USERPOINTS_EXPIRY_DESCRIPTION', 'userpoints_expiry_description');
define('USERPOINTS_EXPIREON_DATE', 'userpoints_expireon_date');
define('USERPOINTS_EXPIREAFTER_DATE', 'userpoints_expireafter_date');
define('USERPOINTS_DISPLAY_MESSAGE', 'userpoints_display_message');
define('USERPOINTS_REPORT_USERCOUNT', 'userpoints_report_usercount');
define('USERPOINTS_REPORT_LIMIT', 'userpoints_report_limit');
define('USERPOINTS_REPORT_DISPLAYZERO', 'userpoints_report_displayzero');
define('USERPOINTS_CATEGORY_NAME', 'Userpoints');
define('USERPOINTS_CATEGORY_DEFAULT_VID', 'userpoints_category_default_vid');
define('USERPOINTS_CATEGORY_DEFAULT_TID', 'userpoints_category_default_tid');
define('USERPOINTS_CATEGORY_PROFILE_DISPLAY_TID', 'userpoints_category_profile_display_tid');
define('USERPOINTS_TRANSACTION_TIMESTAMP', 'userpoints_transaction_timestamp');

/**
 * Returns an array of common translation placeholders.
 */
function userpoints_translation() {
  static $trans;
  if (!isset($trans)) {
    $trans = array(
      '!Points' => check_plain(variable_get(USERPOINTS_TRANS_UCPOINTS, 'Points')),
      '!points' => check_plain(variable_get(USERPOINTS_TRANS_LCPOINTS, 'points')),
      '!Point' => check_plain(variable_get(USERPOINTS_TRANS_UCPOINT, 'Point')),
      '!point' => check_plain(variable_get(USERPOINTS_TRANS_LCPOINT, 'point')),
      '!Uncategorized' => check_plain(variable_get(USERPOINTS_TRANS_UNCAT, 'General')),
    );
  }
  return $trans;
}

/*
 * Returns an array of possible transaction statuses.
 */
function userpoints_txn_status() {
  static $stati;
  if (empty($stati)) {
    $stati = array(
      UserpointsTransaction::STATUS_APPROVED => t('Approved'),
      UserpointsTransaction::STATUS_PENDING => t('Pending'),
      UserpointsTransaction::STATUS_DECLINED => t('Declined'),
    );
  }
  return $stati;
}

/**
 * Implements hook_help().
 */
function userpoints_help($path, $arg) {
  switch ($path) {
    case 'admin/settings/userpoints':
      return t('Configure userpoints moderation and branding translation');
    case 'admin/help#userpoints':
      return t('Users earn !points as they post nodes, comments, and vote on nodes', userpoints_translation());
  }
}

/**
 * Checks access for administrative functionality.
 *
 * Provides simplified access checks for the administrative permissions:
 * - administer userpoints
 * - add userpoints
 * - edit userpoints
 * - moderate userpoints
 *
 * @param $type
 *   The access type to check. The administer permission has access to all of
 *   them. Supported strings:
 *   - list: Access to the userpoints list, default local task. All
 *           administrative permissions have access to this.
 *   - add: Permission to add new userpoints transactions.
 *   - edit: Permission to edit existing userpoints transactions.
 *   - moderate: Permission to approve/decline pending transactions.
 *   - administer: Unlimited userpoints permissions, used for settings page.
 *
 * @return
 *   TRUE if the current user has access, FALSE if not.
 */
function userpoints_admin_access($type = 'list') {

  // Administer userpoints permission has full access.
  if (user_access('administer userpoints')) {
    return TRUE;
  }
  switch ($type) {

    // All admin permissions have access to the list page.
    case 'list':
      return user_access('add userpoints') || user_access('edit userpoints') || user_access('moderate userpoints');
      break;
    case 'add':
      return user_access('add userpoints');
      break;
    case 'edit':
      return user_access('edit userpoints');
      break;
    case 'moderate':
      return user_access('moderate userpoints');
      break;
    case 'administer':

      // administer permission was already checked, this exists for
      // documentation purposes only.
      break;
  }
  return FALSE;
}

/**
 * Implements hook_menu().
 */
function userpoints_menu() {
  $items = array();
  $items['admin/config/people/userpoints'] = array(
    'title' => '!Points',
    'title arguments' => userpoints_translation(),
    'description' => strtr('Manage !points', userpoints_translation()),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_admin_points',
    ),
    'access callback' => 'userpoints_admin_access',
    'access arguments' => array(
      'list',
    ),
    'file' => 'userpoints.admin.inc',
  );
  $items['admin/config/people/userpoints/list'] = array(
    'title' => 'Totals',
    'file' => 'userpoints.admin.inc',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -2,
  );
  $items['admin/config/people/userpoints/transaction'] = array(
    'title' => 'Transactions',
    'title arguments' => userpoints_translation(),
    'description' => 'List transactions',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_admin_transactions',
      FALSE,
    ),
    'access callback' => 'userpoints_admin_access',
    'access arguments' => array(
      'edit',
    ),
    'file' => 'userpoints.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/config/people/userpoints/moderate'] = array(
    'title' => 'Moderation',
    'title arguments' => userpoints_translation(),
    'description' => strtr('Review !points in moderation', userpoints_translation()),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_admin_transactions',
      TRUE,
    ),
    'access callback' => 'userpoints_admin_access',
    'access arguments' => array(
      'moderate',
    ),
    'file' => 'userpoints.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  $items['admin/config/people/userpoints/add'] = array(
    'title' => 'Add !points transaction',
    'title arguments' => userpoints_translation(),
    'description' => 'Admin add/delete userpoints',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_admin_txn',
      4,
      5,
    ),
    'access callback' => 'userpoints_admin_access',
    'access arguments' => array(
      'add',
    ),
    'file' => 'userpoints.admin.inc',
    'type' => MENU_LOCAL_ACTION,
  );
  $items['admin/config/people/userpoints/settings'] = array(
    'title' => '!Points settings',
    'description' => strtr('Settings for !points', userpoints_translation()),
    'title arguments' => userpoints_translation(),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_admin_settings',
    ),
    'access callback' => 'userpoints_admin_access',
    'access arguments' => array(
      'administer',
    ),
    'file' => 'userpoints.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 10,
  );
  $items['userpoints'] = array(
    'title' => 'Users by !points',
    'title arguments' => userpoints_translation(),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_list_users',
    ),
    'access arguments' => array(
      'view userpoints',
    ),
    'file' => 'userpoints.pages.inc',
    'type' => MENU_NORMAL_ITEM,
  );
  $items['userpoints/operation-autocomplete'] = array(
    'title' => 'Operation autocomplete',
    'page callback' => 'userpoints_operation_autocomplete',
    'access callback' => 'userpoints_admin_access',
    'access arguments' => array(
      'add',
    ),
    'file' => 'userpoints.admin.inc',
    'type' => MENU_CALLBACK,
  );
  $items['myuserpoints'] = array(
    'title' => 'My !points',
    'title arguments' => userpoints_translation(),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_list_transactions',
    ),
    'access callback' => 'userpoints_access_transactions',
    'file' => 'userpoints.pages.inc',
    'type' => MENU_NORMAL_ITEM,
    'menu_name' => 'user-menu',
  );
  $items['myuserpoints/%'] = array(
    'title' => 'My !points',
    'title arguments' => userpoints_translation(),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_list_transactions',
      NULL,
      1,
    ),
    'access callback' => 'userpoints_access_transactions',
    'file' => 'userpoints.pages.inc',
    'type' => MENU_NORMAL_ITEM,
    'menu_name' => 'user-menu',
  );
  $items['user/%user/points'] = array(
    'title' => '!Points',
    'title arguments' => userpoints_translation(),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userpoints_list_transactions',
      1,
    ),
    'access callback' => 'userpoints_access_transactions',
    'access arguments' => array(
      1,
    ),
    'file' => 'userpoints.pages.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  );

  // There are separate, duplicated local tasks for transactions in the
  // administrative area, myuserpoints and the userpoints of another user.
  // They all need to be created separately because local tasks must be menu
  // router items, but it can be done in a loop since the only difference is
  // the path prefix and position of the argument.
  $local_task_prefixes = array(
    'admin/config/people/userpoints/transaction',
    'myuserpoints/transaction',
    'user/%user/points',
  );
  foreach ($local_task_prefixes as $local_task_prefix) {

    // The dynamic argument is always the first after the prefix.
    $pos = count(explode('/', $local_task_prefix));
    $items[$local_task_prefix . '/list'] = array(
      'title' => 'List',
      'type' => MENU_DEFAULT_LOCAL_TASK,
      'weight' => -15,
    );
    $items[$local_task_prefix . '/%userpoints_transaction/view'] = array(
      'title' => 'View',
      'page callback' => 'userpoints_view_transaction',
      'page arguments' => array(
        $pos,
      ),
      'access callback' => 'userpoints_access_view_transaction',
      'access arguments' => array(
        $pos,
      ),
      'file' => 'userpoints.pages.inc',
      'type' => MENU_LOCAL_TASK,
      'weight' => -10,
    );
    $items[$local_task_prefix . '/%userpoints_transaction/edit'] = array(
      'title' => 'Edit',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'userpoints_admin_txn',
        $pos + 1,
        $pos,
      ),
      'access callback' => 'userpoints_admin_access',
      'access arguments' => array(
        'edit',
      ),
      'file' => 'userpoints.admin.inc',
      'type' => MENU_LOCAL_TASK,
      'weight' => -5,
    );
    $items[$local_task_prefix . '/%userpoints_transaction/approve'] = array(
      'title' => 'Approve',
      'title arguments' => userpoints_translation(),
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'userpoints_confirm_approve',
        $pos + 1,
        $pos,
      ),
      'access callback' => 'userpoints_admin_access_transaction_pending',
      'access arguments' => array(
        $pos,
      ),
      'file' => 'userpoints.admin.inc',
      'type' => MENU_LOCAL_TASK,
    );
    $items['user/%user/points/%userpoints_transaction/decline'] = array(
      'title' => 'Decline',
      'title arguments' => userpoints_translation(),
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'userpoints_confirm_approve',
        $pos + 1,
        $pos,
      ),
      'access callback' => 'userpoints_admin_access_transaction_pending',
      'access arguments' => array(
        $pos,
      ),
      'file' => 'userpoints.admin.inc',
      'type' => MENU_LOCAL_TASK,
    );
  }
  return $items;
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function userpoints_menu_local_tasks_alter(&$data, $router_item, $root_path) {

  // Add action link to add points on 'userpoints' administration pages.
  if (strpos($root_path, 'admin/config/people/userpoints/') !== FALSE) {

    // Don't display the action link on some pages like settings and
    // approve or decline confirmation forms.
    $blacklist = array(
      'settings',
      'approve',
      'decline',
      'add',
      'edit',
      'types',
    );
    foreach ($blacklist as $blacklisted_path) {
      if (strpos($root_path, $blacklisted_path) !== FALSE) {
        return;
      }
    }
    $item = menu_get_item('admin/config/people/userpoints/add');

    // For the transaction view pages, we want to directly link to the
    // user for this transaction.
    if (arg(4) == 'transaction' && arg(6) == 'view') {
      $transaction = userpoints_transaction_load(arg(5));
      $item['href'] .= '/' . $transaction->uid;
    }
    if ($item['access']) {
      $data['actions']['output'][] = array(
        '#theme' => 'menu_local_action',
        '#link' => $item,
      );
    }
  }
}

/**
 * Access callback for approve and decline local tasks.
 *
 * Only pending transactions can be approved or declined.
 */
function userpoints_admin_access_transaction_pending(UserpointsTransaction $transaction) {
  return $transaction
    ->isPending() && userpoints_admin_access('moderate');
}

/**
 * Checks if user can access their points - used via hook_menu().
 *
 * @param $account
 *   (optional) The account to check; if not given use currently
 *   logged in user.
 *
 * @return
 *   TRUE if user has permissions to view userpoints and if the user
 *   is logged in.
 */
function userpoints_access_my_points($account = NULL) {
  if (userpoints_admin_access('edit')) {
    return TRUE;
  }
  return user_access('view userpoints') && user_is_logged_in() || user_access('view own userpoints');
}

/**
 * Checks if a user has access to own or other users transactions history.
 *
 * The user must be logged in to have access both, own or other users
 * transactions.
 *
 * @param $account
 *   (optional) The account to check; if not given use currently
 *   logged in user.
 *
 * @return
 *   TRUE if the user has access to view the transactions of the requested
 *   account and FALSE otherwise.
 */
function userpoints_access_transactions($account = NULL) {
  global $user;

  // Other users accounts.
  if ($account && $user->uid != $account->uid) {
    return (user_access('view userpoints transactions') || userpoints_admin_access('edit')) && user_is_logged_in();
  }

  // Own user account.
  $user_has_transactions_permissions = user_access('view own userpoints transactions') || user_access('view userpoints transactions') ? TRUE : FALSE;
  return ($user_has_transactions_permissions || userpoints_admin_access('edit')) && user_is_logged_in();
}

/**
 * Checks if a user has access to a transaction.
 *
 * @return
 *   TRUE if the user has permissions to view the transaction.
 */
function userpoints_access_view_transaction(UserpointsTransaction $transaction) {
  return userpoints_access_my_points($transaction
    ->getUser());
}

/**
 * Implements hook_permission().
 */
function userpoints_permission() {
  return array(
    'view own userpoints' => array(
      'title' => t('View own !points', userpoints_translation()),
      'description' => t('Allows to view own !points.', userpoints_translation()),
    ),
    'view userpoints' => array(
      'title' => t('View all !points', userpoints_translation()),
      'description' => t('Allows to view the !points of other users.', userpoints_translation()),
    ),
    'view own userpoints transactions' => array(
      'title' => t('View own transactions'),
      'description' => t('Allows to view own userpoints transactions history.', userpoints_translation()),
    ),
    'view userpoints transactions' => array(
      'title' => t('View all transactions'),
      'description' => t('Allows to view the userpoints transactions history of other users.', userpoints_translation()),
    ),
    'add userpoints' => array(
      'title' => t('Add new !point transactions', userpoints_translation()),
      'description' => t('Allows to create new !point transactions.', userpoints_translation()),
    ),
    'edit userpoints' => array(
      'title' => t('Edit !point transactions', userpoints_translation()),
      'description' => t('Allows to modify existing !point transactions, including the ability to view transaction history for all users.', userpoints_translation()),
    ),
    'moderate userpoints' => array(
      'title' => t('Moderate !point transactions', userpoints_translation()),
      'description' => t('Allows to approve or disapprove !point transactions.', userpoints_translation()),
    ),
    'administer userpoints' => array(
      'title' => t('Administer Userpoints'),
      'description' => t('Allows to configure the settings and includes full read and write access of all !point transactions.', userpoints_translation()),
    ),
  );
}

/**
 * Implements hook_theme().
 */
function userpoints_theme() {
  return array(
    'userpoints_view_category' => array(
      'render element' => 'element',
      'file' => 'userpoints.theme.inc',
    ),
    'userpoints_view_item' => array(
      'render element' => 'element',
      'file' => 'userpoints.theme.inc',
    ),
    'userpoints_points' => array(
      'variables' => array(
        'points' => 0,
      ),
      'file' => 'userpoints.theme.inc',
    ),
  );
}

/**
 * Implements hook_tokens().
 */
function userpoints_tokens($type, $tokens, array $data = array(), array $options = array()) {
  $url_options = array(
    'absolute' => TRUE,
  );
  if (isset($options['language'])) {
    $url_options['language'] = $options['language'];
    $language_code = $options['language']->language;
  }
  else {
    $language_code = NULL;
  }
  $replacements = array();
  if ($type == 'user' && !empty($data['user'])) {
    $user = $data['user'];
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'points':
          $points = userpoints_get_current_points($user->uid);
          $replacements[$original] = theme('userpoints_points', array(
            'points' => $points,
          ));
          break;
        case 'maxpoints':
          $points = userpoints_get_max_points($user->uid);
          $replacements[$original] = theme('userpoints_points', array(
            'points' => $points,
          ));
        default:
          break;
      }
    }
    if ($points_tokens = token_find_with_prefix($tokens, 'points')) {
      $replacements += token_generate('userpoints', $points_tokens, $data, $options);
    }
    if ($points_tokens = token_find_with_prefix($tokens, 'maxpoints')) {
      $replacements += token_generate('maxuserpoints', $points_tokens, $data, $options);
    }
  }
  if ($type == 'userpoints' && !empty($data['user'])) {
    foreach ($tokens as $name => $original) {
      $tid = NULL;
      if ($name == 'all') {
        $tid = 'all';
      }
      elseif (strpos($name, 'category-') === 0) {

        // Extract the category id from the string that looks like category-1.
        list(, $tid) = explode('-', $name);
      }
      if ($tid) {
        $points = userpoints_get_current_points($data['user']->uid, $tid);
        $replacements[$original] = theme('userpoints_points', array(
          'points' => $points,
        ));
      }
    }
  }
  if ($type == 'maxuserpoints' && !empty($data['user'])) {
    $uid = is_object($data['user']->uid) ? $data['user']
      ->getIdentifier() : $data['user']->uid;
    foreach ($tokens as $name => $original) {
      $tid = NULL;
      if ($name == 'all') {
        $tid = 'all';
      }
      elseif (strpos($name, 'category-') === 0) {

        // Extract the category id from the string that looks like category-1.
        list(, $tid) = explode('-', $name);
      }
      if ($tid) {
        $points = userpoints_get_max_points($uid, $tid);
        $replacements[$original] = theme('userpoints_points', array(
          'points' => $points,
        ));
      }
    }
  }
  return $replacements;
}

/**
 * Implements hook_token_info().
 */
function userpoints_token_info() {
  $types = array(
    'userpoints' => array(
      'name' => t('!Points', userpoints_translation()),
      'description' => t('Amount of !points a user has.', userpoints_translation()),
      'needs-data' => 'user',
    ),
    'maxuserpoints' => array(
      'name' => t('Maximal !points', userpoints_translation()),
      'description' => t('Maximal amount of !points a user had at any time.', userpoints_translation()),
      'needs-data' => 'user',
    ),
  );
  $tokens = array();
  $tokens['user']['points'] = array(
    'name' => 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()),
    'type' => 'userpoints',
  );
  $tokens['user']['maxpoints'] = array(
    'name' => t('Maximal !points', userpoints_translation()),
    'description' => t('The highest amount of !points a user had at any given point. If there are multiple categories, only the default category is taken into account.', userpoints_translation()),
    'type' => 'userpoints',
  );
  $categories = userpoints_get_categories();
  if (count($categories) > 1) {
    foreach ($categories as $tid => $category) {
      $tokens['userpoints']['category-' . $tid] = array(
        'name' => t('!Points in category %category', array_merge(array(
          '%category' => $category,
        ), userpoints_translation())),
        'description' => t('The amount of !points this user has in that category.', userpoints_translation()),
      );
      $tokens['maxuserpoints']['category-' . $tid] = array(
        'name' => t('Maximal !points in category %category', array_merge(array(
          '%category' => $category,
        ), userpoints_translation())),
        'description' => t('The highest amount of !points a user had at any given point in that category.', userpoints_translation()),
      );
    }
  }
  $tokens['userpoints']['all'] = array(
    'name' => t('Total !points', userpoints_translation()),
    'description' => t('Total amount of !points over all categories.', userpoints_translation()),
  );
  $tokens['maxuserpoints']['all'] = array(
    'name' => t('Total maximum !points', userpoints_translation()),
    'description' => t('Total amount of maximal !points over all categories.', userpoints_translation()),
  );
  return array(
    'types' => $types,
    'tokens' => $tokens,
  );
}

/**
 * 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.
 *
 * @ingroup userpoints_api
 */
function userpoints_get_current_points($uid = NULL, $tid = NULL) {
  $points = drupal_static(__FUNCTION__, array());
  if (!$uid) {
    global $user;
    $uid = $user->uid;
  }

  // 0 is a valid value for the Uncategorized category.
  if (!isset($tid)) {
    $tid = userpoints_get_default_tid();
  }
  if (!isset($points[$uid][$tid])) {
    if ($tid === 'all') {
      $points[$uid][$tid] = (int) db_query('SELECT points FROM {userpoints_total} WHERE uid = :uid', array(
        ':uid' => $uid,
      ))
        ->fetchField();
    }
    else {
      $points[$uid][$tid] = (int) db_query('SELECT points FROM {userpoints} WHERE uid = :uid AND tid = :tid', array(
        ':uid' => $uid,
        ':tid' => $tid,
      ))
        ->fetchField();
    }
  }
  return $points[$uid][$tid];
}

/**
 * Gets the number of maximal points of that user.
 *
 * @param $uid
 *   User id of the user to get or lose the points.
 *
 * @return
 *   Number of max points in that user's account.
 *
 * @ingroup userpoints_api
 */
function userpoints_get_max_points($uid = NULL, $tid = NULL) {
  $max = drupal_static(__FUNCTION__, array());

  // Checks if uid is passed as a parameter.
  if (!$uid) {

    // It is not, so we use the currently logged in user's uid.
    global $user;
    $uid = $user->uid;
  }

  // Checks if a term id is passed as a parameter.
  if (!isset($tid)) {

    // It is not, so get the default term id.
    $tid = userpoints_get_default_tid();
  }

  // Checks if we have already cached the maximum for the user/term combination on previous calls.
  if (!isset($max[$uid][$tid])) {

    // We did not cache it.
    if ($tid === 'all') {

      // There is no term id, so we select the total.
      $max[$uid][$tid] = db_query('SELECT max_points FROM {userpoints_total} WHERE uid = :uid', array(
        ':uid' => $uid,
      ))
        ->fetchField();
    }
    else {

      // A term ID is specified, so fetch its maximum points.
      $max[$uid][$tid] = db_query('SELECT max_points FROM {userpoints} WHERE uid = :uid AND tid = :tid', array(
        ':uid' => $uid,
        ':tid' => $tid,
      ))
        ->fetchField();
    }
  }

  // Return the cached value.
  return $max[$uid][$tid];
}

/**
 * Grant a user points.
 *
 * The function expects three required parameters, an operation string, the
 * amount of points, and the transaction bundle. Optionally, a user id may be
 * passed.
 *
 * The function then returns a UserpointsTransaction object, which provides
 * methods to add further details to the transaction. New transactions are saved
 * automatically through the __destruct() method. However, if transaction needs
 * to be saved immediately, save() can be called directly.
 *
 * Basic usage examples:
 * @code
 * // Adding points to the current user, relying on automatic saving.
 * userpoints_grant_points('mymodule_type_action', $points,
 *                         'my_userpoints_type');
 *
 * // Grant points to another, add a entity reference to a node and save
 * // explicitly.
 * userpoints_grant_points('mymodule_type_otheraction', $points,
 *                         'my_userpoints_type', $account->uid)
 *   ->setEntity('node', $node->nid)
 *   ->save();
 * @endcode
 *
 * A list of all available methods can be found in the UserpointsTransaction
 * documentation.
 *
 * @param $operation
 *   A string that can identify this transaction. Can be used to provide a
 *   custom, translatable, optionally dynamic reason for this transaction in
 *   transaction listings. See hook_userpoints_info().
 * @param $points
 *   A positive or negative point amount that should be assigned to the user.
 * @param $type
 *   The userpoints transaction bundle to create. Optional, defaults to the
 *   default bundle if it exists.
 * @param $uid
 *   UID of the user that should be granted points. Optional, defaults to the
 *   current user.
 *
 * @return UserpointsTransaction
 *
 * @ingroup userpoints_api
 */
function userpoints_grant_points($operation, $points, $type = NULL, $uid = NULL) {
  global $user;
  if (empty($type)) {

    // Default to the default bundle if not set.
    $type = variable_get('userpoints_default_bundle', 'userpoints');
  }
  if (empty($uid)) {

    // Default to the current user if not set.
    $uid = $user->uid;
  }
  try {
    $transaction = new UserpointsTransaction(array(
      'type' => $type,
    ));
  } catch (Exception $e) {
    watchdog_exception('userpoints', $e, 'Unable to create !points transaction.', userpoints_translation());
  }
  return $transaction
    ->setOperation($operation)
    ->setPoints($points)
    ->setUid($uid);
}

/**
 * Determines the correct default expiration date.
 *
 * @return
 *   The default expiration date.
 */
function userpoints_get_default_expiry_date() {
  $expirydate = userpoints_date_to_timestamp(variable_get(USERPOINTS_EXPIREON_DATE, 0));
  if ($expirydate < REQUEST_TIME) {
    $expirydate = variable_get(USERPOINTS_EXPIREAFTER_DATE, 0);
    if ($expirydate) {
      $expirydate = REQUEST_TIME + $expirydate;
    }
  }
  return (int) $expirydate;
}

/**
 * Implements hook_user_delete().
 */
function userpoints_user_delete($account) {

  // The user is being deleted, delete all traces in userpoints and txn tables.
  db_delete('userpoints')
    ->condition('uid', $account->uid)
    ->execute();
  db_delete('userpoints_txn')
    ->condition('uid', $account->uid)
    ->execute();
}

/**
 * Implements hook_user_view().
 */
function userpoints_user_view($account, $view_mode) {
  global $user;
  if (user_access('view userpoints') || user_access('view own userpoints') && $user->uid == $account->uid) {
    $points_list = userpoints_get_points_list($account);
    if (!empty($details) || $points_list) {
      $account->content['userpoints'] = array(
        'title' => array(
          '#markup' => '<h3>' . t('!Points', userpoints_translation()) . '</h3>',
        ),
        '#weight' => 0,
      );
      if ($points_list) {
        $account->content['userpoints'] += $points_list;
      }
    }
  }
}

/**
 * Implements hook_field_extra_fields().
 */
function userpoints_field_extra_fields() {
  $extra['user']['user'] = array(
    'display' => array(
      'userpoints' => array(
        'label' => t('!Points', userpoints_translation()),
        'description' => t('!Points related information and actions.', userpoints_translation()),
        'weight' => 0,
      ),
    ),
  );
  $extra['userpoints_transaction']['userpoints_transaction'] = array(
    'form' => array(
      'txn_points' => array(
        'label' => t('Transaction user'),
        'description' => t('The user of the transaction'),
        'weight' => -20,
      ),
      'points' => array(
        'label' => t('!Points', userpoints_translation()),
        'description' => t('!Points amount of the transaction', userpoints_translation()),
        'weight' => -15,
      ),
    ),
  );
  if (module_exists('taxonomy') && count(userpoints_get_categories()) > 1) {
    $extra['userpoints_transaction']['userpoints_transaction']['form']['tid'] = array(
      'label' => t('Category'),
      'description' => t('Category of the transaction'),
      'weight' => 0,
    );
  }

  /*$extra['userpoints_transaction']['userpoints_transaction']['form']['additional_settings'] = array(
      'label' => t('Additional settings'),
      'description' => t('Additional settings'),
      'weight' => 20,
    );*/
  return $extra;
}

/**
 * Returns a render array that displays the points and action links.
 *
 * @param $account
 *   User object for which the points should be displayed.
 * @return
 *   Render array with the points and actions.
 */
function userpoints_get_points_list($account = NULL) {
  global $user;
  if (empty($account)) {
    $account = $user;
  }
  $output = array();
  $categories = userpoints_get_categories();

  // 0 can not be used as a checkbox value.
  $categories = array(
    'uncategorized' => $categories[0],
  ) + $categories + array(
    'all' => t('Total !points in all categories', userpoints_translation()),
  );
  unset($categories[0]);
  $tids = array_filter(variable_get(USERPOINTS_CATEGORY_PROFILE_DISPLAY_TID, array_keys($categories)));
  if (!empty($tids)) {
    $points_list = array();
    $total = NULL;
    foreach ($tids as $tid) {

      // Which points are we displaying. Special case for uncategorized.
      $points = userpoints_get_current_points($account->uid, $tid == 'uncategorized' ? 0 : $tid);
      $points = theme('userpoints_points', array(
        'points' => $points,
      ));
      if ($tid == 'all') {
        $total = t('Total (all categories): @points', userpoints_translation() + array(
          '@points' => $points,
        ));
      }
      else {
        $points_list[] = t('%category: @points', userpoints_translation() + array(
          '@points' => $points,
          '%category' => $categories[$tid],
        ));
      }
    }

    // If there are multiple categories, create a list.
    $output['list'] = array(
      '#theme' => 'item_list',
      '#items' => $points_list,
      '#attributes' => array(
        'class' => array(
          'userpoints-points',
        ),
      ),
    );
    if ($total) {
      $output['total'] = array(
        '#markup' => '<div class="userpoints-total">' . $total . '</div>',
      );
    }
  }
  $links = array();
  if (userpoints_access_transactions($account)) {
    $links['userpoints-view'] = array(
      'title' => t('View !points transactions', userpoints_translation()),
      'href' => $user->uid == $account->uid ? 'myuserpoints' : 'user/' . $account->uid . '/points',
    );
  }
  if (userpoints_admin_access('add')) {
    $links['userpoints-adjust'] = array(
      'title' => t('Add or deduct !points', userpoints_translation()),
      'href' => 'admin/config/people/userpoints/add/' . $account->uid,
    );
  }
  $output['actions'] = array(
    '#theme' => 'links__userpoints_actions',
    '#links' => $links,
    '#attributes' => array(
      'class' => array(
        'links',
        'userpoints-links',
      ),
    ),
    '#attached' => array(
      'css' => array(
        drupal_get_path('module', 'userpoints') . '/userpoints.css',
      ),
    ),
  );
  return $output;
}

/**
 * Provides a dropdown to filter by category.
 */
function userpoints_filter_form($account = NULL, $values = array()) {
  $categories = userpoints_get_categories($account);
  $form = array();
  if (count($categories) > 1) {
    $categories = array(
      'all' => t('Display all'),
    ) + $categories;
    $form['tid'] = array(
      '#type' => 'select',
      '#title' => t('Filter by category'),
      '#options' => $categories,
      '#default_value' => isset($values['tid']) ? $values['tid'] : 'all',
      '#ajax' => array(
        'callback' => 'userpoints_filter_form_ajax_callback',
        'wrapper' => 'userpoints_list_wrapper',
      ),
    );
  }
  return $form;
}

/**
 * Ajax callback for userpoints filter form.
 */
function userpoints_filter_form_ajax_callback($form, $form_state) {
  $commands = array();

  // First, replace the points listing.
  $commands[] = ajax_command_replace('#userpoints_list_wrapper', drupal_render($form['list']));

  // Bartik uses the page-title id, Seven has a class of that name. Replace
  // the title for both of them and assume that most other themes use the
  // same.
  $commands[] = ajax_command_html('h1#page-title, h1.page-title', drupal_get_title());
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Parse input and generate an values array.
 *
 * @param $form_state
 *   Form state with the submitted values.
 * @param $tid
 *   Category id to be used as a default.
 *
 * @return
 *   Array of values to be used with userpoints_filter_form().
 */
function userpoints_filter_parse_input($form_state, $tid = NULL) {

  // Enforce tid if passed in through the URL.
  $values = isset($form_state['values']) ? $form_state['values'] : array(
    'tid' => NULL,
  );
  if (!isset($values['tid'])) {
    if (isset($_GET['tid'])) {
      $values['tid'] = $_GET['tid'];
    }
    elseif ($tid) {
      $values['tid'] = $tid;
    }
  }
  if (isset($values['tid'])) {

    // Add tid argument to GET.
    $_GET['tid'] = $values['tid'];
  }
  return $values;
}

/**
 * Filter a query according to the selected filters.
 */
function userpoints_filter_query(SelectQueryInterface $query, $values) {

  // Checks for filtering. isset() is used because 0 is a valid value
  // (Uncategorized).
  if (isset($values['tid']) && $values['tid'] != 'all') {

    // If a category is selected, limit both the default query and the query
    // that displays pending points to this category.
    $query
      ->condition('p.tid', (int) $values['tid']);
    $categories = userpoints_get_categories();
    return $categories[$values['tid']];
  }
}

/**
 * Implements hook_block_info().
 */
function userpoints_block_info() {
  $blocks[-1]['info'] = t('User\'s !points', userpoints_translation());

  // Grab a list of the available terms.
  $terms = userpoints_get_categories();
  foreach ($terms as $key => $value) {
    $blocks[$key]['info'] = t("Highest @term !points", userpoints_translation() + array(
      '@term' => $value,
    ));
  }
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function userpoints_block_view($delta) {
  global $user;
  if ($delta == -1 && (user_access('view userpoints') || user_access('view own userpoints'))) {
    $title = t('My !points balance', userpoints_translation());
    if ($user->uid) {
      $content = userpoints_get_points_list();
    }
    else {
      $content = t('!Points are visible to logged in users only', userpoints_translation());
    }
  }
  elseif (user_access('view userpoints')) {

    // $delta is our tid for pulling the points.
    // If 0 we pull 0 or NULL.
    $title = t('Highest Users');
    $query = db_select('userpoints', 'p')
      ->fields('p', array(
      'uid',
      'points',
    ))
      ->orderBy('p.points', 'DESC')
      ->range(0, variable_get('userpoints_block_up_records_' . $delta, 5));
    if ($delta == 0) {
      $query
        ->condition(db_or()
        ->condition('p.tid', 0)
        ->isNull('p.tid'));
    }
    else {
      $query
        ->condition('p.tid', $delta);
    }

    // Exclude blocked users.
    $query
      ->join('users', 'u', 'u.uid = p.uid AND u.status = 1');
    $rows = array();
    foreach ($query
      ->execute() as $data) {
      $rows[] = array(
        array(
          'data' => theme('username', array(
            'account' => user_load($data->uid),
          )),
        ),
        array(
          'data' => $data->points,
          'align' => 'right',
        ),
      );
    }
    $header = array(
      t('User'),
      t('!Points', userpoints_translation()),
    );
    $content = theme('table', array(
      'header' => $header,
      'rows' => $rows,
    ));
    $content .= '<div class="more-link">' . l(t('more'), 'userpoints/' . $delta, array(
      'attributes' => array(
        'title' => t('All users by !points', userpoints_translation()),
      ),
    )) . '</div>';
  }
  if (!empty($title) && !empty($content)) {
    $block['subject'] = $title;
    $block['content'] = $content;
    return $block;
  }
}

/**
 * Implements hook_block_configure().
 */
function userpoints_block_configure($delta) {
  if ($delta > 1) {
    $form['up_records'] = array(
      '#type' => 'select',
      '#title' => t('Number of users to display'),
      '#default_value' => variable_get('userpoints_block_up_records_' . $delta, 10),
      '#options' => array(
        1 => 1,
        5 => 5,
        10 => 10,
        15 => 15,
        20 => 20,
        30 => 30,
        40 => 40,
        50 => 50,
        60 => 60,
        70 => 70,
        80 => 80,
        90 => 90,
        100 => 100,
        200 => 200,
      ),
      '#description' => t('Limit the number of users displayed to this value'),
    );
    return $form;
  }
}

/**
 * Implements hook_block_save().
 */
function userpoints_block_save($delta, $edit) {
  variable_set('userpoints_block_up_records_' . $delta, isset($edit['up_records']) ? $edit['up_records'] : 10);
}

/**
 * returns an array of possible expiry times
 * to the administrative settings page
 */
function userpoints_expiry_dates() {
  return array(
    NULL => 'Never',
    3600 => 'One hour',
    86400 => 'One Day',
    604800 => 'One Week',
    1209600 => 'Two Weeks',
    2419200 => 'Four Weeks',
    31536000 => '365 Days',
  );
}

/**
 * Modifies FAPI date setting to timestamp.
 *
 * @return
 *   UNIX timestamp.
 */
function userpoints_date_to_timestamp($date) {

  //This takes the FAPI date form array and returns a timestamp
  if ($date) {
    return mktime(0, 0, 0, $date['month'], $date['day'], $date['year']);
  }
}

/**
 * Finds and expires expired points.
 *
 * Finds all transactions with a expirydate < REQUEST_TIME and posts
 * opposite transactions (sum of 0).
 */
function userpoints_expire_transactions() {
  $sql = "SELECT txn_id\n          FROM {userpoints_txn}\n          WHERE status = 0 AND expired = 0\n          AND (expirydate < :expiry_date AND expirydate != 0)";
  $txn_ids = db_query($sql, array(
    ':expiry_date' => REQUEST_TIME,
  ))
    ->fetchCol();
  foreach (userpoints_transaction_load_multiple($txn_ids) as $transaction) {
    $time_stamp_formatted = format_date($transaction->time_stamp, 'custom', 'Y-m-d H:i');
    $arguments = array_merge(userpoints_translation(), array(
      '!operation' => $transaction->operation,
      '!description' => $transaction->description,
      '!txn_id' => $transaction->txn_id,
      '!date' => $time_stamp_formatted,
    ));
    $description = strtr(variable_get(USERPOINTS_EXPIRY_DESCRIPTION, NULL), $arguments);
    userpoints_grant_points('expiry', -$transaction->points, $transaction->type, $transaction->uid)
      ->setDescription($description)
      ->setParent($transaction->txn_id)
      ->setTid($transaction->tid)
      ->setExpiryDate(0)
      ->save();

    // Ok we've expired the entry, now the original transaction needs to be
    // marked as expired.
    $transaction
      ->setExpired(1)
      ->save();
  }
}

/**
 * Implements hook_cron().
 */
function userpoints_cron() {
  userpoints_expire_transactions();
}

/**
 *  Returns the Vocabulary ID (vid) used by userpoints for categorization.
 *
 *  If no vocab exists it will create one.
 */
function userpoints_get_vid() {
  if (!module_exists('taxonomy')) {
    return FALSE;
  }

  // Code lovingly inspired by the image.module w/ code by drewish.
  $vid = variable_get(USERPOINTS_CATEGORY_DEFAULT_VID, '');
  if (empty($vid) || !taxonomy_vocabulary_load($vid)) {
    $sql = "SELECT vid FROM {taxonomy_vocabulary} WHERE module='userpoints'";
    $vid = db_query($sql)
      ->fetchField();
    if (!$vid) {
      drupal_set_message(t("Created Userpoints vocabulary"));

      // No vocabulary exists, we'll create one.
      $vocab = (object) array(
        'name' => USERPOINTS_CATEGORY_NAME,
        'description' => t('Automatically created by the userpoints module'),
        'machine_name' => 'userpoints',
        'multiple' => '0',
        'required' => '0',
        'hierarchy' => '1',
        'relations' => '0',
        'module' => 'userpoints',
      );
      taxonomy_vocabulary_save($vocab);
      $vid = $vocab->vid;
    }
    variable_set(USERPOINTS_CATEGORY_DEFAULT_VID, $vid);
  }
  if (!is_numeric($vid)) {
    watchdog('userpoints', 'userpoints module was unable to select or create a vocabulary. !Points will be uncategorized', array(), WATCHDOG_ERROR);
  }
  return $vid;
}

/**
 * Returns an array of possible categories, suitable for inclusion in FAPI.
 *
 * @ingroup userpoints_api
 */
function userpoints_get_categories($account = NULL) {
  $cache = drupal_static(__FUNCTION__, array());
  $key = $account ? $account->uid : 0;
  if (!isset($cache[$key])) {

    // Create the "Uncategorized" category.
    $options = array();
    $options[0] = t('!Uncategorized', userpoints_translation());
    if (module_exists('taxonomy')) {
      $vid = userpoints_get_vid();
      if ($vid) {

        // If an account is passed, load the terms directly from the database.
        if ($account) {
          $query = db_select('taxonomy_term_data', 't')
            ->fields('t', array(
            'tid',
            'name',
          ))
            ->condition('t.vid', userpoints_get_vid())
            ->groupBy('t.tid')
            ->groupBy('t.name')
            ->groupBy('t.weight')
            ->orderBy('t.weight');
          $query
            ->join('userpoints_txn', 'p', 't.tid = p.tid AND p.uid = :uid', array(
            ':uid' => $account->uid,
          ));
          $terms = $query
            ->execute();
        }
        else {
          $terms = taxonomy_get_tree($vid);
        }
        foreach ($terms as $term) {
          $options[$term->tid] = $term->name;
        }
      }
    }
    $cache[$key] = $options;
  }
  return $cache[$key];
}

/**
 * Wrapper function to return the default tid via API call
 */
function userpoints_get_default_tid() {
  return (int) variable_get(USERPOINTS_CATEGORY_DEFAULT_TID, 0);
}

/**
 * Implements hook_views_api().
 */
function userpoints_views_api() {
  return array(
    'api' => 2.0,
  );
}

/**
 * Returns information about point-providing modules and operations.
 *
 * @see hook_userpoints_info()
 */
function userpoints_get_info($operation = NULL) {
  static $info = NULL;
  if (!isset($info)) {

    // Collect information.
    $info = module_invoke_all('userpoints_info');

    // Allow other modules to alter that information.
    drupal_alter('userpoints_info', $info);
  }
  if ($operation) {
    if (isset($info[$operation])) {
      return $info[$operation];
    }
    return NULL;
  }
  return $info;
}

/**
 * Implements hook_userpoints_info().
 */
function userpoints_userpoints_info() {
  return array(
    'expiry' => array(
      'description' => t('!Points have expired.', userpoints_translation()),
      'admin description' => t('Expire an existing transaction'),
    ),
  );
}

/**
 * Loads a userpoints transaction.
 *
 * @param $txn_id
 *   Userpoints transaction Id.
 *
 * @return UserpointsTransaction
 *   A loaded userpoints transaction object.
 */
function userpoints_transaction_load($txn_id, $reset = FALSE) {
  $txn_ids = !empty($txn_id) ? array(
    $txn_id,
  ) : array();
  $temp = userpoints_transaction_load_multiple($txn_ids, array(), $reset);
  return $temp ? reset($temp) : FALSE;
}

/**
 * Loads multiple userpoints transactions.
 */
function userpoints_transaction_load_multiple(array $txn_ids, $conditions = array(), $reset = FALSE) {
  return entity_load('userpoints_transaction', $txn_ids, $conditions, $reset);
}

/**
 * Loads userpoints transaction type.
 *
 * @param $name
 *   Userpoints transaction bundle name.
 *
 * @return UserpointsTransactionType
 *   A userpoints transaction type entity.
 */
function userpoints_transaction_type_load($name) {
  return userpoints_transaction_get_types($name);
}

/**
 * Checks if the userpoints transaction type exists.
 *
 * @param $name
 *   Userpoints transaction bundle name.
 *
 * @return bool
 */
function userpoints_transaction_type_exists($name) {
  $type = userpoints_transaction_type_load($name);
  if ($type) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Loads userpoints transaction types.
 *
 * @param $name
 *   An optional userpoints transaction bundle name.
 *
 * @return Mixed
 *   An array of userpoints transaction types or a UserpointsTransactionType.
 */
function userpoints_transaction_get_types($name = NULL) {
  $types = entity_load_multiple_by_name('userpoints_transaction_type', isset($name) ? array(
    $name,
  ) : FALSE);
  return isset($name) ? reset($types) : $types;
}

/**
 * Access callback for administration access to transaction type ui.
 */
function userpoints_transaction_type_access($op, $type) {
  return user_access('administer userpoints');
}

/**
 * Returns a table header for a transaction listing.
 *
 * @param $settings
 *   Array with settings about which column shall be displayed. All settings
 *   default to TRUE.
 *   - show_category, show category column.
 *   - show_user, show user column.
 *   - show_status, show status column.
 * @return
 *   Table header definition for theme_table() and TableSort.
 */
function userpoints_get_transaction_header($settings) {
  $settings += array(
    'show_category' => count(userpoints_get_categories()) > 1,
    'show_user' => TRUE,
    'show_status' => TRUE,
  );
  $header = array();
  if ($settings['show_user']) {
    $header[] = array(
      'data' => t('User'),
      'field' => 'uid',
      'class' => array(
        'userpoints-transactions-header-status',
      ),
    );
  }
  $header[] = array(
    'data' => t('!Points', userpoints_translation()),
    'field' => 'points',
    'class' => array(
      'userpoints-transactions-header-points',
    ),
  );

  // Only display category if there is more than one category. In contrast to
  // the filter, this is not specific for the categories. If there are
  // categories, we want tell the user in which he has points, even if he
  // only has points in a single category.
  if ($settings['show_category']) {
    $header[] = array(
      'data' => t('Category'),
      'field' => 't.name',
      'class' => array(
        'userpoints-transactions-header-category',
      ),
    );
  }
  $header[] = array(
    'data' => t('Date'),
    'field' => 'time_stamp',
    'sort' => 'desc',
    'class' => array(
      'userpoints-transactions-header-timestamp',
    ),
  );
  $header[] = array(
    'data' => t('Reason'),
    'class' => array(
      'userpoints-transactions-header-reason',
    ),
  );
  if ($settings['show_status']) {
    $header[] = array(
      'data' => t('Status'),
      'field' => 'status',
      'class' => array(
        'userpoints-transactions-header-status',
      ),
    );
  }
  $header[] = array(
    'data' => t('Actions'),
    'class' => array(
      'userpoints-transactions-header-actions',
    ),
  );
  return $header;
}

/**
 * Returns the header array definition for userpoints listings.
 */
function userpoints_get_list_header() {
  $header = array(
    array(
      'data' => t('User'),
      'field' => 'u.name',
    ),
  );
  if (count(userpoints_get_categories()) > 1) {
    $header[] = array(
      'data' => t('Category'),
      'field' => 't.name',
    );
  }
  $header[] = array(
    'data' => t('!Points', userpoints_translation()),
    'field' => 'p.points',
    'sort' => 'desc',
  );
  return $header;
}
function userpoints_get_list_row($data) {
  global $user;
  $categories = userpoints_get_categories();
  $details = '';
  if ($user->uid == $data->uid) {
    $details = "&nbsp;&nbsp;" . l(t("details"), 'myuserpoints');
  }
  elseif (userpoints_admin_access('edit')) {
    $details = "&nbsp;&nbsp;" . l(t("details"), 'user/' . $data->uid . '/points');
  }
  $name = theme('username', array(
    'account' => $data,
  ));
  $row = array(
    array(
      'data' => $details ? t('!name (!details)', array(
        '!name' => $name,
        '!details' => $details,
      )) : $name,
    ),
  );
  if (count($categories) > 1) {
    $row[] = array(
      'data' => isset($categories[$data->tid]) ? $categories[$data->tid] : $categories[0],
      'align' => 'right',
    );
  }
  $points = theme('userpoints_points', array(
    'points' => $data->points,
  ));
  $row[] = array(
    'data' => $points,
    'align' => 'right',
  );
  return $row;
}

/**
 * Gets the property from the UserpointsTransaction object.
 */
function userpoints_transaction_property_get($data, array $options, $name) {
  $method = 'get' . str_replace('_', '', $name);
  if (method_exists($data, $method)) {
    $value = $data
      ->{$method}();
    return $value;
  }
  return NULL;
}

/**
 * Gets the property from the UserpointsTransaction object.
 */
function userpoints_transaction_property_set($data, $name, $value) {
  $method = 'set' . str_replace('_', '', $name);
  if (method_exists($data, $method)) {
    return $data
      ->{$method}($value);
  }
  return NULL;
}

/**
 * Gets the absolute points from a transaction..
 */
function userpoints_transaction_get_points_absolute($userpoints_transaction, array $options, $name) {
  if (is_object($userpoints_transaction)) {
    return abs($userpoints_transaction->points);
  }
  return NULL;
}

/**
 * Implements hook_entity_info().
 */
function userpoints_entity_info() {
  $return = array(
    'userpoints_transaction' => array(
      'module' => 'userpoints',
      'label' => t('Userpoints Transaction'),
      'entity class' => 'UserpointsTransaction',
      'controller class' => 'UserpointsTransactionController',
      'metadata controller class' => 'UserpointsTransactionMetadataController',
      'views controller class' => 'EntityDefaultViewsController',
      'base table' => 'userpoints_txn',
      'uri callback' => 'entity_class_uri',
      'fieldable' => TRUE,
      'entity keys' => array(
        'id' => 'txn_id',
        'bundle' => 'type',
      ),
      'bundle keys' => array(
        'bundle' => 'name',
      ),
      'bundles' => array(
        'userpoints' => array(
          'label' => t('Default'),
          'admin' => array(
            'path' => 'admin/config/people/userpoints/types/%userpoints_transaction_type',
            'real path' => 'admin/config/people/userpoints/types/userpoints',
            'bundle argument' => 5,
            'access callback' => 'userpoints_admin_access',
            'access arguments' => array(
              'administer userpoints',
            ),
          ),
        ),
      ),
      'view modes' => array(
        'full' => array(
          'label' => t('Full content'),
          'custom settings' => FALSE,
        ),
      ),
    ),
    'userpoints_transaction_type' => array(
      'module' => 'userpoints',
      'label' => t('Userpoints Transaction Type'),
      'entity class' => 'UserpointsTransactionType',
      'controller class' => 'EntityAPIControllerExportable',
      'base table' => 'userpoints_txn_type',
      'entity keys' => array(
        'id' => 'id',
        'name' => 'name',
        'label' => 'label',
      ),
      'fieldable' => FALSE,
      'bundle of' => 'userpoints_transaction',
      'access callback' => 'userpoints_transaction_type_access',
      'exportable' => TRUE,
      'admin ui' => array(
        'path' => 'admin/config/people/userpoints/types',
        'file' => 'userpoints.admin.inc',
        'controller class' => 'UserpointsTransactionTypeUIController',
      ),
    ),
  );
  return $return;
}

/**
 * Implements hook_entity_info_alter().
 */
function userpoints_entity_info_alter(&$info) {
  $types = userpoints_transaction_get_types();
  if (!empty($types)) {
    foreach ($types as $name => $type) {
      $info['userpoints_transaction']['bundles'][$name] = array(
        'label' => check_plain($type->label),
        'admin' => array(
          'path' => 'admin/config/people/userpoints/types/%userpoints_transaction_type',
          'real path' => 'admin/config/people/userpoints/types/' . $name,
          'bundle argument' => 5,
          'access callback' => 'userpoints_admin_access',
          'access arguments' => array(
            'administer userpoints',
          ),
        ),
      );
    }
  }
}

Functions

Namesort descending Description
userpoints_access_my_points Checks if user can access their points - used via hook_menu().
userpoints_access_transactions Checks if a user has access to own or other users transactions history.
userpoints_access_view_transaction Checks if a user has access to a transaction.
userpoints_admin_access Checks access for administrative functionality.
userpoints_admin_access_transaction_pending Access callback for approve and decline local tasks.
userpoints_block_configure Implements hook_block_configure().
userpoints_block_info Implements hook_block_info().
userpoints_block_save Implements hook_block_save().
userpoints_block_view Implements hook_block_view().
userpoints_cron Implements hook_cron().
userpoints_date_to_timestamp Modifies FAPI date setting to timestamp.
userpoints_entity_info Implements hook_entity_info().
userpoints_entity_info_alter Implements hook_entity_info_alter().
userpoints_expire_transactions Finds and expires expired points.
userpoints_expiry_dates returns an array of possible expiry times to the administrative settings page
userpoints_field_extra_fields Implements hook_field_extra_fields().
userpoints_filter_form Provides a dropdown to filter by category.
userpoints_filter_form_ajax_callback Ajax callback for userpoints filter form.
userpoints_filter_parse_input Parse input and generate an values array.
userpoints_filter_query Filter a query according to the selected filters.
userpoints_get_categories Returns an array of possible categories, suitable for inclusion in FAPI.
userpoints_get_current_points Get current points of a user.
userpoints_get_default_expiry_date Determines the correct default expiration date.
userpoints_get_default_tid Wrapper function to return the default tid via API call
userpoints_get_info Returns information about point-providing modules and operations.
userpoints_get_list_header Returns the header array definition for userpoints listings.
userpoints_get_list_row
userpoints_get_max_points Gets the number of maximal points of that user.
userpoints_get_points_list Returns a render array that displays the points and action links.
userpoints_get_transaction_header Returns a table header for a transaction listing.
userpoints_get_vid Returns the Vocabulary ID (vid) used by userpoints for categorization.
userpoints_grant_points Grant a user points.
userpoints_help Implements hook_help().
userpoints_menu Implements hook_menu().
userpoints_menu_local_tasks_alter Implements hook_menu_local_tasks_alter().
userpoints_permission Implements hook_permission().
userpoints_theme Implements hook_theme().
userpoints_tokens Implements hook_tokens().
userpoints_token_info Implements hook_token_info().
userpoints_transaction_get_points_absolute Gets the absolute points from a transaction..
userpoints_transaction_get_types Loads userpoints transaction types.
userpoints_transaction_load Loads a userpoints transaction.
userpoints_transaction_load_multiple Loads multiple userpoints transactions.
userpoints_transaction_property_get Gets the property from the UserpointsTransaction object.
userpoints_transaction_property_set Gets the property from the UserpointsTransaction object.
userpoints_transaction_type_access Access callback for administration access to transaction type ui.
userpoints_transaction_type_exists Checks if the userpoints transaction type exists.
userpoints_transaction_type_load Loads userpoints transaction type.
userpoints_translation Returns an array of common translation placeholders.
userpoints_txn_status
userpoints_userpoints_info Implements hook_userpoints_info().
userpoints_user_delete Implements hook_user_delete().
userpoints_user_view Implements hook_user_view().
userpoints_views_api Implements hook_views_api().

Constants