$form_state['values']['txn_id'], 'approver_uid' => $user->uid, 'status' => $form_state['values']['operation'], ); userpoints_userpointsapi($params); $form_state['redirect'] = 'admin/config/people/userpoints/moderate'; } /** * Form builder for add/edit userpoints transaction form. */ function userpoints_admin_txn($form, &$form_state, $mode, $txn_id = NULL) { global $user; drupal_add_css(drupal_get_path('module', 'userpoints') . '/userpoints.css'); $timestamp = format_date(REQUEST_TIME, 'custom', 'Y-m-d H:i O'); if ($mode == 'edit' && $txn_id) { $txn = db_query('SELECT * FROM {userpoints_txn} WHERE txn_id = :txn_id', array(':txn_id' => $txn_id))->fetch(); if (!$txn) { // Failed to load transaction, display not found page. drupal_not_found(); drupal_exit(); } $timestamp = format_date($txn->time_stamp, 'custom', 'Y-m-d H:i:s O'); $txn_user = user_load($txn->uid); $form['txn'] = array( '#type' => 'value', '#value' => $txn, ); } elseif ($mode == 'add' && $txn_id) { $txn_user = user_load($txn_id); } elseif ($mode == 'edit') { // Edit but now transaction id given, display not found page. drupal_not_found(); drupal_exit(); } $form['txn_user'] = array( '#type' => 'textfield', '#title' => t('User Name'), '#size' => 30, '#maxlength' => 60, '#default_value' => isset($txn_user) ? $txn_user->name : '', '#autocomplete_path' => $mode == 'edit' ? NULL : 'user/autocomplete', '#description' => t('The name of the user who should gain or lose !points.', userpoints_translation()), '#required' => TRUE, '#weight' => -20, '#disabled' => $mode == 'edit', ); $form['points'] = array( '#type' => 'textfield', '#title' => t('Points'), '#size' => 10, '#maxlength' => 10, '#default_value' => isset($txn->points) ? $txn->points : 0, '#description' => t('The number of !points to add or subtract. For example, enter %positive to add !points or %negative to deduct !points.', array('%positive' => 25, '%negative' => -25) + userpoints_translation()), '#required' => TRUE, '#weight' => -15, ); if (module_exists('taxonomy')) { $options = userpoints_get_categories(); $form['tid'] = array( '#type' => 'select', '#title' => t('Category'), '#default_value' => isset($txn->tid) ? $txn->tid : userpoints_get_default_tid(), '#options' => $options, '#description' => t('The !points category that should apply to this transaction.', userpoints_translation()), '#weight' => 0, // Only show the category if there are actually categories to choose from. '#access' => count($options) > 1, ); } $form['additional_settings'] = array( '#type' => 'vertical_tabs', ); $form['status'] = array( '#type' => 'fieldset', '#title' => t('Status'), '#group' => 'additional_settings', ); if ($mode == 'add') { $form['status']['moderate'] = array( '#title' => t('Moderated'), '#type' => 'checkbox', '#description' => t('If checked, this !points transaction must be approved, through the moderation process.', userpoints_translation()), '#default_value' => variable_get(USERPOINTS_POINTS_MODERATION, 0), '#access' => userpoints_admin_access('moderate'), '#weight' => -10, ); } else { $form['status']['status'] = array( '#title' => t('Approval status'), '#type' => 'radios', '#options' => userpoints_txn_status(), '#description' => t('Approval status of the transaction.'), '#default_value' => $txn->status, '#access' => userpoints_admin_access('moderate'), '#weight' => -10, ); } $form['status']['time_stamp'] = array( '#type' => 'textfield', '#title' => t('Date/Time'), '#default_value' => $timestamp, '#size' => 30, '#maxlength' => 30, '#description' => t('The date and time recorded for this transaction. Use this format: YYYY-MM-DD HH:MM +ZZZZ.'), '#weight' => -5, // Do not show this if it is not allowed to change the timestamp anyway. '#access' => !variable_get(USERPOINTS_TRANSACTION_TIMESTAMP, 1), ); $expirydate = 0; if (isset($txn->txn_id)) { if ($txn->expirydate > 0) { $expirydate = format_date($txn->expirydate, 'custom', 'Y-m-d H:i:s O'); } } else { // If we're not editing we use site defaults. $expirydate = userpoints_get_default_expiry_date(); if ($expirydate) { $expirydate = format_date($expirydate, 'custom', 'Y-m-d H:i:s O'); } } $form['status']['expirydate'] = array( '#type' => 'textfield', '#title' => t('Expiration date'), '#default_value' => $expirydate ? $expirydate : '', '#size' => 30, '#maxlength' => 30, '#description' => t('The date and time that the !points should expire. Use this format: YYYY-MM-DD HH:MM +ZZZZ. Leave this field blank if the !points should never expire.', userpoints_translation()), '#weight' => 25, ); $form['reason'] = array( '#type' => 'fieldset', '#title' => t('Reason'), '#group' => 'additional_settings', ); $form['reason']['operation'] = array( '#type' => 'textfield', '#title' => t('Operation'), '#default_value' => isset($txn->operation) ? $txn->operation : t('admin'), '#maxlength' => 48, '#description' => t('The operation type for this transaction (default is %admin). Any value is valid but using a defined operation will cause an auto-generated description (specific to the chosen operation) to be included. This description can be translated into multiple languages.', array('%admin' => t('admin'))), '#weight' => 5, '#required' => FALSE, '#autocomplete_path' => 'userpoints/operation-autocomplete', ); $form['reason']['description'] = array( '#type' => 'textarea', '#title' => t('Description'), '#default_value' => isset($txn->description) ? $txn->description : '', '#rows' => 7, '#cols' => 40, '#description' => t('Enter an optional description for this transaction, such as the reason !points were added or subtracted.', userpoints_translation()), '#weight' => 10, ); $form['reference'] = array( '#type' => 'fieldset', '#title' => t('Reference'), '#group' => 'additional_settings', ); $options = array('' => '< ' . t('None') . ' >'); foreach (entity_get_info() as $type => $info) { $options[$type] = $info['label']; } $form['reference']['entity_type'] = array( '#type' => 'select', '#title' => t('Linked entity'), '#weight' => 0, '#options' => $options, '#default_value' => isset($txn->entity_type) ? $txn->entity_type : '', ); $form['reference']['entity_id'] = array( '#type' => 'textfield', '#title' => t('Entity ID'), '#title_display' => 'invisible', '#weight' => 5, '#size' => 5, '#maxlength' => 20, '#default_value' => isset($txn->entity_id) ? $txn->entity_id : '', '#description' => t('Choose the entity type and ID to be referenced. A link to the entity will be shown.'), ); $form['reference']['reference'] = array( '#type' => 'textfield', '#title' => t('Internal reference'), '#default_value' => isset($txn->reference) ? $txn->reference : '', '#size' => 30, '#maxlength' => 128, '#description' => t('Enter an optional reference code for this transaction. This is for internal tracking and is not shown to the end user.', userpoints_translation()), '#weight' => 10, ); $approved_by = !empty($txn->approver_uid) ? user_load($txn->approver_uid) : NULL; if ($approved_by) { $form['status']['approver'] = array( '#type' => 'textfield', '#title' => t('Moderator'), '#default_value' => $approved_by->name, '#size' => 30, '#maxlength' => 30, '#description' => t('The user who gave the transaction its current status.'), '#weight' => 30, ); } $form['mode'] = array( '#type' => 'hidden', '#default_value' => $mode ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), '#weight' => 50, ); return $form; } /** * Autocomplete callback for search an operation. * * @param $search * Search string. */ function userpoints_operation_autocomplete($search) { $results = array(); if (!empty($search)) { foreach (userpoints_get_info() as $operation => $info) { if (strpos($operation, $search) !== FALSE) { $results[$operation] = userpoints_create_operation_autocomplete_label($operation, $info, $search); } elseif (isset($info['admin description']) && strpos($info['admin description'], $search) !== FALSE) { $results[$operation] = userpoints_create_operation_autocomplete_label($operation, $info, $search); } elseif (isset($info['description']) && strpos($info['description'], $search) !== FALSE) { $results[$operation] = userpoints_create_operation_autocomplete_label($operation, $info, $search); } } } drupal_json_output((object)$results); } /** * Create a autocomplete label with highlighted search text. * * @param $operation * Operation string. * @param $info * Operation info array. * @param $search * Search text that will be highlighted if found. * * @return * Highlighted label. If existing, the admin description is used and if not, * the operation string. */ function userpoints_create_operation_autocomplete_label($operation, $info, $search) { $label = $operation; if (!empty($info['admin description'])) { $label = $info['admin description']; } return preg_replace("/(" . preg_quote($search) . ")/i","$1", $label); } /** * Validate function for userpoints transaction form. */ function userpoints_admin_txn_validate($form, &$form_state) { $txn_user = user_load_by_name($form_state['values']['txn_user']); if (!is_object($txn_user)) { form_set_error('txn_user', t('Specified user does not exist.')); } else { form_set_value($form['txn_user'], $txn_user, $form_state); } if ((int)$form_state['values']['points'] == 0) { form_set_error('points', t('Amount of !points must be a positive or negative number.', userpoints_translation())); } if (!strtotime($form_state['values']['time_stamp'])) { form_set_error('time_stamp', t('The provided timestamp is not a valid date.')); } } /** * Submit function for userpoints transaction form. */ function userpoints_admin_txn_submit($form, &$form_state) { global $user; if ($form_state['values']['mode'] == 'add') { $params = array( 'points' => $form_state['values']['points'], 'uid' => $form_state['values']['txn_user']->uid, 'operation' => $form_state['values']['operation'], 'description' => $form_state['values']['description'], 'reference' => $form_state['values']['reference'], 'tid' => $form_state['values']['tid'], 'time_stamp' => strtotime($form_state['values']['time_stamp']), 'moderate' => (bool)$form_state['values']['moderate'], 'approver_uid' => $user->uid, ); if ($form_state['values']['expirydate']) { // Check for the existence of an expirydate. $params['expirydate'] = strtotime($form_state['values']['expirydate']); } if (!empty($form_state['values']['entity_id']) && !empty($form_state['values']['entity_type'])) { $params['entity_type'] = $form_state['values']['entity_type']; $params['entity_id'] = (int)$form_state['values']['entity_id']; } } else { $expirydate = 0; if (!empty($form_state['values']['expirydate'])) { $expirydate = strtotime($form_state['values']['expirydate']); } // If status changed, the current user is the new approver, when not // changed, then the current approver is kept. if ($form_state['values']['txn']->status == $form_state['values']['status']) { $approver_uid = $form_state['values']['txn']->approver_uid; } else { $approver_uid = $user->uid; } $params = array( 'uid' => $form_state['values']['txn']->uid, 'approver_uid' => $approver_uid, 'points' => $form_state['values']['points'], 'tid' => $form_state['values']['tid'], 'time_stamp' => strtotime($form_state['values']['time_stamp']), 'operation' => $form_state['values']['operation'], 'description' => $form_state['values']['description'], 'reference' => $form_state['values']['reference'], 'status' => $form_state['values']['status'], 'expirydate' => $expirydate, 'txn_id' => $form_state['values']['txn']->txn_id, 'display' => FALSE, ); if (!empty($form_state['values']['entity_id']) && !empty($form_state['values']['entity_type'])) { $params['entity_type'] = $form_state['values']['entity_type']; $params['entity_id'] = (int)$form_state['values']['entity_id']; } drupal_set_message(t('Changes to the !points transaction have been saved.', userpoints_translation())); } userpoints_userpointsapi($params); $form_state['redirect'] = 'admin/config/people/userpoints'; } /** * Provides an administrative interface for managing points. */ function userpoints_admin_points($tid = NULL) { $categories = userpoints_get_categories(); $show_category = count($categories) > 1; $header = array( array('data' => t('User'), 'field' => 'u.name'), array('data' => t('Category'), 'field' => 't.name'), array('data' => t('!Points', userpoints_translation()), 'field' => 'p.points', 'sort' => 'desc'), ); $query = db_select('userpoints', 'p')->extend('PagerDefault')->extend('TableSort') ->fields('p', array('uid', 'points', 'tid')) ->fields('u', array('name')) ->groupBy('p.uid') ->groupBy('u.name') ->groupBy('p.points') ->groupBy('p.tid') ->groupBy('t.name') ->orderByHeader($header) ->limit(variable_get(USERPOINTS_REPORT_USERCOUNT, 30)); $query->join('users', 'u', 'p.uid = u.uid'); $query->leftJoin('taxonomy_term_data', 't', 'p.tid = t.tid'); // Check for filtering. isset() is used because 0 is a valid value // (Uncategorized). if (isset($tid)) { // 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)$tid); $active_category = $categories[$tid]; } if (isset($active_category)) { drupal_set_title(t('Totals (%category category)', userpoints_translation() + array('%category' => $active_category)), PASS_THROUGH); } else { drupal_set_title(t('Totals')); } if (variable_get(USERPOINTS_REPORT_DISPLAYZERO, 1) == 0) { // The user would NOT like to see users with zero points. $query->condition('p.points', 0, '<>'); } $rows = array(); foreach ($query->execute() as $data) { $link = userpoints_admin_access('edit') ? l(t("(details)"), "myuserpoints/$data->uid") : ''; $rows[] = array( array('data' => trim(theme('username', array('account' => $data)) . ' ' . $link)), array('data' => isset($categories[$data->tid]) ? $categories[$data->tid] : $categories[0], 'align' => 'right'), array('data' => $data->points, 'align' => 'right'), ); } // If there is only one category there is no sense in display the category filter dropdown. $output = array(); if ($categories > 1) { $output['filter'] = drupal_get_form('userpoints_filter_cat_select', 'admin/config/people/userpoints/', $tid); } $output['table'] = array( '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); $output['pager'] = array( '#theme' => 'pager', ); return $output; } /** * Displays a list of transactions. * */ function userpoints_admin_transactions($tid = NULL) { // Load the categories and check if there are multiples or only a single one. $categories = userpoints_get_categories(); $show_category = count($categories) > 1; // Store context in the output array so that modules have access to it. $output = array( '#tid' => $tid, '#attached' => array( 'css' => array( drupal_get_path('module', 'userpoints') . '/userpoints.css', ), ), ); // Only display the category selection if there is more than one category // to select from. This check is specific to the categories the user has // points in. if ($show_category) { $output['form'] = drupal_get_form('userpoints_filter_cat_select', 'admin/config/people/userpoints/list/transactions/', $tid); $output['form']['#weight'] = -10; } $settings = array( 'show_category' => $show_category, ); $header = userpoints_get_transaction_header($settings); $query = db_select('userpoints_txn', 'p')->extend('PagerDefault')->extend('TableSort') ->fields('p') ->orderByHeader($header) // Enforce consistent sort order. ->orderBy('p.txn_id', 'DESC') ->limit(variable_get(USERPOINTS_REPORT_USERCOUNT, 30)); $query->leftJoin('taxonomy_term_data', 't', 'p.tid = t.tid'); // Check for filtering. isset() is used because 0 is a valid value // (Uncategorized). if (isset($tid)) { // 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)$tid); $active_category = $categories[$tid]; } if (isset($active_category)) { drupal_set_title(t('Transactions (%category category)', userpoints_translation() + array('%category' => $active_category)), PASS_THROUGH); } else { drupal_set_title(t('Transactions')); } $rows = array(); foreach ($query->execute() as $transaction) { $rows[] = userpoints_get_transaction_row($transaction, $settings); } $output['table'] = array( '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No !Points earned', userpoints_translation()), '#weight' => -5, '#attributes' => array('class' => array('userpoints-transactions-list')), ); $output['pager'] = array( '#theme' => 'pager', '#weight' => 0, ); return $output; } function userpoints_admin_manage($tid = NULL) { $categories = userpoints_get_categories(); $show_category = count($categories) > 1; // Store context in the output array so that modules have access to it. $output = array( '#tid' => $tid, '#attached' => array( 'css' => array( drupal_get_path('module', 'userpoints') . '/userpoints.css', ), ), ); $settings = array( 'show_category' => $show_category, 'show_status' => FALSE, ); $header = userpoints_get_transaction_header($settings); $query = db_select('userpoints_txn', 'p')->extend('PagerDefault')->extend('TableSort') ->fields('p', array('txn_id', 'uid', 'time_stamp', 'points', 'operation', 'status', 'entity_type', 'entity_id', 'tid')) ->condition('p.status', USERPOINTS_TXN_STATUS_PENDING) ->orderByHeader($header) // Enforce consistent sort order. ->orderBy('p.txn_id', 'DESC') ->limit(variable_get(USERPOINTS_REPORT_USERCOUNT, 30)); $query->leftJoin('taxonomy_term_data', 't', 'p.tid = t.tid'); // Check for filtering. isset() is used because 0 is a valid value // (Uncategorized). if (isset($tid)) { // 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)$tid); $active_category = $categories[$tid]; } if (isset($active_category)) { drupal_set_title(t('Moderation (%category category)', userpoints_translation() + array('%category' => $active_category)), PASS_THROUGH); } else { drupal_set_title(t('Moderation')); } $rows = array(); foreach ($query->execute() as $data) { $rows[] = userpoints_get_transaction_row($data, $settings); } if ($show_category) { $output['filter'] = drupal_get_form('userpoints_filter_cat_select', 'admin/config/people/userpoints/moderate/', $tid); } $output['table'] = array( '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No !points awaiting moderation', userpoints_translation()), '#attributes' => array('class' => array('userpoints-moderation-list')), ); $output['pager'] = array( '#theme' => 'pager', ); return $output; } function userpoints_confirm_approve($form, $form_state, $operation, $txn_id) { $form = array( 'txn_id' => array( '#type' => 'value', '#value' => $txn_id, ), ); $transaction = userpoints_transaction_load($txn_id); $arguments = array( '!user' => theme('username', array('account' => $transaction->user)), '%category' => $transaction->category, ) + userpoints_translation(); if ($operation == 'approve') { $question = format_plural($transaction->points, 'Do you want to approve @count !point for !user in the %category category?', 'Do you want to approve @count !points for !user in the %category category?', $arguments); $form['operation'] = array( '#type' => 'value', '#value' => USERPOINTS_TXN_STATUS_APPROVED, ); } else { $question = format_plural($transaction->points, 'Do you want to decline @count !point for !user in the %category category?', 'Do you want to decline @count !points for !user in the %category category?', $arguments); $form['operation'] = array( '#type' => 'value', '#value' => USERPOINTS_TXN_STATUS_DECLINED, ); } return confirm_form($form, $question, 'admin/config/people/userpoints/moderate', t('Reason: !reason', array('!reason' => userpoints_create_description($transaction)))); } /** * Menu callback for settings form. */ function userpoints_admin_settings($form, &$form_state) { drupal_set_title(t('!Points settings', userpoints_translation())); drupal_add_js(drupal_get_path('module', 'userpoints') . '/userpoints_admin.js'); $form['settings'] = array( '#prefix' => '