You are here

uc_price_per_role.module in Ubercart Price Per Role 6

Same filename and directory in other branches
  1. 5 uc_price_per_role.module
  2. 7 uc_price_per_role.module

File

uc_price_per_role.module
View source
<?php

/**
 * Implementation of hook_perm().
 */
function uc_price_per_role_perm() {
  return array(
    'access price selection block',
  );
}

/**
 * Implementation of hook_menu().
 */
function uc_price_per_role_menu() {
  $items = array();
  $items['admin/store/settings/price_per_role'] = array(
    'title' => 'Price per role settings',
    'description' => 'Configure price per role settings.',
    'access arguments' => array(
      'administer store',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'uc_price_per_role_settings_form',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  if (module_exists('uc_attribute')) {
    $items['node/%node/edit/option_prices'] = array(
      'title' => 'Option prices',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'uc_price_per_role_option_prices_form',
        1,
      ),
      'access callback' => 'uc_attribute_product_option_access',
      'access arguments' => array(
        1,
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 3,
    );
  }
  return $items;
}

/**
 * Implementation of hook_menu_alter().
 */
function uc_price_per_role_menu_alter(&$items) {

  // Make room in local menu for the 'Option prices' tab.
  if (module_exists('uc_attribute')) {
    $items['node/%node/edit/adjustments']['weight'] = $items['node/%node/edit/adjustments']['weight'] + 1;
  }
  if (isset($items['node/%node/edit/features'])) {
    $items['node/%node/edit/features']['weight'] = $items['node/%node/edit/features']['weight'] + 1;
  }
}

/**
 * Implementation of hook_theme().
 */
function uc_price_per_role_theme() {
  return array(
    'uc_price_per_role_settings_form' => array(
      'file' => 'uc_price_per_role.module',
      'arguments' => array(
        'form' => NULL,
      ),
    ),
    'uc_price_per_role_product_prices' => array(
      'file' => 'uc_price_per_role.module',
      'arguments' => array(
        'prices' => NULL,
      ),
    ),
    'uc_price_per_role_option_prices_form' => array(
      'file' => 'uc_price_per_role.module',
      'arguments' => array(
        'form' => NULL,
      ),
    ),
  );
}
function uc_price_per_role_settings_form() {
  $enabled = variable_get('uc_price_per_role_enabled', array());
  $weights = variable_get('uc_price_per_role_weights', array());
  $roles = user_roles();
  foreach (array_keys($roles) as $rid) {
    if (!isset($weights[$rid])) {
      $weights[$rid] = 0;
    }
  }
  asort($weights);
  $form['help'] = array(
    '#value' => t('Enable roles that require separate pricing. For users with more than one matching role, the lightest weight role that has a price available will be used.'),
  );
  $form['fields']['#tree'] = TRUE;
  foreach ($weights as $rid => $weight) {
    $form['fields'][$rid]['role'] = array(
      '#value' => $roles[$rid],
    );
    $form['fields'][$rid]['enabled'] = array(
      '#type' => 'checkbox',
      '#default_value' => $enabled[$rid],
    );
    $form['fields'][$rid]['weight'] = array(
      '#type' => 'weight',
      '#delta' => 5,
      '#default_value' => $weight,
    );
  }
  $form['buttons']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  return $form;
}
function theme_uc_price_per_role_settings_form($form) {
  $output = drupal_render($form['help']);
  $header = array(
    t('Enable'),
    t('Role'),
    t('Weight'),
  );
  $rows = array();
  foreach (element_children($form['fields']) as $field) {
    $row = array();
    $row[] = drupal_render($form['fields'][$field]['enabled']);
    $row[] = drupal_render($form['fields'][$field]['role']);
    $row[] = drupal_render($form['fields'][$field]['weight']);
    $rows[] = $row;
  }
  $output .= theme('table', $header, $rows);
  $output .= drupal_render($form);
  return $output;
}
function uc_price_per_role_settings_form_submit($form, &$form_state) {
  $enabled = array();
  $weights = array();
  foreach ($form_state['values']['fields'] as $rid => $field) {
    $enabled[$rid] = $field['enabled'];
    $weights[$rid] = $field['weight'];
  }
  variable_set('uc_price_per_role_enabled', $enabled);
  variable_set('uc_price_per_role_weights', $weights);
}

/**
 * Implementation of hook_form_alter().
 */
function uc_price_per_role_form_alter(&$form, $form_state, $form_id) {
  if ($form['#id'] == 'node-form' && isset($form['base']['prices'])) {
    $enabled = variable_get('uc_price_per_role_enabled', array());
    $enabled_roles = array_filter($enabled);

    // If there is an enabled role, change the label on the core Ubercart sell
    // price to indicate it is now the default price.
    if (!empty($enabled_roles)) {
      $form['base']['prices']['sell_price']['#title'] = t('Default sell price');
      $form['base']['prices']['sell_price']['#description'] = t('Default customer purchase price.');
    }
    $form['base']['role_prices'] = array(
      '#weight' => 6,
      '#theme' => 'uc_price_per_role_product_prices',
      '#tree' => TRUE,
    );
    $role_prices = $form['#node']->role_prices;
    foreach (user_roles() as $rid => $role) {
      if ($enabled[$rid]) {
        $form['base']['role_prices'][$rid] = array(
          '#type' => 'textfield',
          '#title' => t('%role price', array(
            '%role' => $role,
          )),
          '#default_value' => isset($role_prices[$rid]) ? uc_store_format_price_field_value($role_prices[$rid]) : '',
          '#description' => t('Purchase price for %role users.', array(
            '%role' => $role,
          )),
          '#size' => 20,
          '#maxlength' => 35,
          '#field_prefix' => variable_get('uc_sign_after_amount', FALSE) ? '' : variable_get('uc_currency_sign', '$'),
          '#field_suffix' => variable_get('uc_sign_after_amount', FALSE) ? variable_get('uc_currency_sign', '$') : '',
        );
      }
    }
  }
  else {
    if ($form_id === 'uc_object_options_form') {
      $form['uc_price_per_role_note'] = array(
        '#value' => '<p>' . t('Note: "Price" column is the default option price. To set option prices per role use the <a href="@link">options prices form</a>.', array(
          '@link' => url('node/' . $form['id']['#value'] . '/edit/option_prices'),
        )) . '</p>',
      );
    }
    else {
      if (strpos($form_id, 'add_to_cart_form')) {

        // Modify product form attribute option prices.
        $format = variable_get('uc_attribute_option_price_format', 'adjustment');
        if (module_exists('uc_attribute') && $format != 'none') {
          $nid = intval($form['nid']['#value']);
          $product = node_load($nid);
          $qty = intval($form['qty']['#value']);
          if (!$qty) {
            $qty = 1;
          }
          $priced_attributes = uc_attribute_priced_attributes($nid);
          $role_prices = uc_price_per_role_load_option_prices($nid);
          foreach (element_children($form['attributes']) as $aid) {
            if (isset($form['attributes'][$aid]['#options'])) {
              $attribute = uc_attribute_load($aid, $nid, 'product');
              $context = array(
                'revision' => 'altered',
                'type' => 'product',
                'subject' => array(
                  'node' => $product,
                ),
                'field' => 'price',
              );
              $product_price = uc_price($product->sell_price, $context);
              foreach (array_keys($form['attributes'][$aid]['#options']) as $oid) {
                $price = uc_price_per_role_find_price($role_prices[$oid]);
                if ($price !== FALSE) {
                  $context = array(
                    'revision' => 'formatted',
                    'type' => 'attribute_option',
                    'subject' => array(
                      'attribute' => $attribute,
                      'option' => $attribute->options[$oid],
                    ),
                    'field' => 'price',
                  );
                  switch ($format) {
                    case 'total':
                      $display_price = in_array($aid, $priced_attributes) ? ', ' . uc_price(($product_price + $price) * $qty, $context) : '';
                      if (count($priced_attributes) == 1) {
                        break;
                      }
                    case 'adjustment':
                      $display_price = $price != 0 ? ', ' . ($price > 0 ? '+' : '') . uc_price($price * $qty, $context) : '';
                      break;
                  }
                  $form['attributes'][$aid]['#options'][$oid] = $attribute->options[$oid]->name . $display_price;
                }
              }
            }
          }
        }
      }
    }
  }
}
function theme_uc_price_per_role_product_prices($prices) {
  $output = '<table><tr>';
  foreach (element_children($prices) as $rid) {
    $output .= '<td>' . drupal_render($prices[$rid]) . '</td>';
  }
  $output .= "</table>\n";
  return $output;
}

/**
 * Implementation of hook_nodeapi().
 */
function uc_price_per_role_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  global $user;
  if (in_array($node->type, uc_product_types())) {
    switch ($op) {
      case 'validate':
        if (isset($node->role_prices)) {
          foreach ($node->role_prices as $rid => $price) {
            if (!empty($price) && !is_numeric($price)) {
              form_set_error('role_prices][' . $rid, t('Price must be a number.'));
            }
          }
        }
        break;
      case 'insert':
      case 'update':
        db_query("DELETE FROM {uc_price_per_role_prices} WHERE vid = %d", $node->vid);
        if (is_array($node->role_prices)) {
          foreach ($node->role_prices as $rid => $price) {
            if (is_numeric($price)) {
              db_query("INSERT INTO {uc_price_per_role_prices} (vid, nid, rid, price) VALUES (%d, %d, %d, %f)", $node->vid, $node->nid, $rid, $price);
            }
          }
        }
        break;
      case 'load':
        $result = db_query("SELECT rid, price FROM {uc_price_per_role_prices} WHERE vid = %d", $node->vid);
        $prices = array();
        while ($row = db_fetch_object($result)) {
          $prices[$row->rid] = $row->price;
        }
        $original_price = $node->sell_price;
        $price = uc_price_per_role_find_price($prices);
        if ($price !== FALSE) {
          $node->sell_price = $price;
        }
        return array(
          'role_prices' => $prices,
          'roleindependent_sell_price' => $original_price,
        );
      case 'prepare':

        // Reload original price for editing.
        $node->sell_price = $node->roleindependent_sell_price;
        break;
      case 'delete':
        db_query("DELETE FROM {uc_price_per_role_prices} WHERE nid = %d", $node->nid);
        break;
      case 'delete revision':
        db_query("DELETE FROM {uc_price_per_role_prices} WHERE vid = %d", $node->vid);
        break;
    }
  }
}

/**
 * Implementation of hook_cart_item().
 */
function uc_price_per_role_cart_item($op, &$item) {
  if (module_exists('uc_attribute')) {
    switch ($op) {
      case 'load':
        $role_prices = uc_price_per_role_load_option_prices($item->nid);
        foreach (_uc_cart_product_get_options($item) as $option) {
          $oid = $option['oid'];
          $price = uc_price_per_role_find_price($role_prices[$oid]);
          if ($price !== FALSE) {
            $item->price += $price - $option['price'];
          }
        }
    }
  }
}

/**
 * Form definition to edit a option prices.
 */
function uc_price_per_role_option_prices_form($form_state, $product) {
  drupal_set_title(check_plain($product->title));
  $role_prices = uc_price_per_role_load_option_prices($product->nid);
  $enabled = array_keys(array_filter(variable_get('uc_price_per_role_enabled', array())));
  $form['help'] = array(
    '#value' => t('Leave any box blank to use the default price for the option.'),
  );
  foreach (uc_product_get_attributes($product->nid) as $aid => $attribute) {
    $form['attributes'][$aid]['name'] = array(
      '#value' => $attribute->name,
    );
    $form['attributes'][$aid]['aid'] = array(
      '#type' => 'hidden',
      '#value' => $attribute->aid,
    );
    $form['attributes'][$aid]['ordering'] = array(
      '#type' => 'value',
      '#value' => $attribute->ordering,
    );
    $form['attributes'][$aid]['options'] = array(
      '#weight' => 2,
    );
    $context = array(
      'type' => 'attribute_option',
      'subject' => array(
        'attribute' => $attribute,
      ),
      'field' => 'price',
    );
    $base_attr = uc_attribute_load($attribute->aid);
    if ($base_attr->options) {
      $result = db_query("\n        SELECT ao.aid, ao.oid, ao.name, ao.price AS default_price, ao.ordering AS default_ordering, po.price, po.ordering, po.ordering IS NULL AS null_order FROM {uc_attribute_options} AS ao\n        LEFT JOIN {uc_product_options} AS po ON ao.oid = po.oid AND po.nid = %d\n        WHERE aid = %d ORDER BY null_order, po.ordering, default_ordering, ao.name", $product->nid, $attribute->aid);
      while ($option = db_fetch_object($result)) {
        $oid = $option->oid;
        $context['revision'] = 'themed';
        $context['subject']['option'] = $option;
        $price = is_null($option->price) ? $option->default_price : $option->price;
        $form['attributes'][$aid]['options'][$oid]['name'] = array(
          '#value' => $option->name,
        );
        $form['attributes'][$aid]['options'][$oid]['price'] = array(
          '#value' => uc_price($price, $context),
        );

        // Include unformatted original price to simplify form alteration.
        $context['revision'] = 'original';
        $form['attributes'][$aid]['options'][$oid]['price_value'] = array(
          '#type' => 'value',
          '#value' => uc_price($price, $context),
        );
        foreach ($enabled as $rid) {
          $form['attributes'][$aid]['options'][$oid]['role_prices'][$rid] = array(
            '#type' => 'textfield',
            '#default_value' => isset($role_prices[$oid][$rid]) ? uc_store_format_price_field_value($role_prices[$oid][$rid]) : '',
            '#size' => 6,
          );
        }
      }
    }
    else {
      $form['attributes'][$aid]['default'] = array(
        '#value' => t('This attribute does not have any options.'),
      );
    }
  }
  if (!empty($form['attributes'])) {
    $form['attributes']['#tree'] = TRUE;
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Submit'),
      '#weight' => 10,
    );
  }
  $form['nid'] = array(
    '#type' => 'value',
    '#value' => $product->nid,
  );
  return $form;
}

/**
 * Theme form to edit option prices.
 */
function theme_uc_price_per_role_option_prices_form($form) {
  $roles = user_roles();
  $enabled = array_keys(array_filter(variable_get('uc_price_per_role_enabled', array())));
  $header = array(
    t('Attribute'),
    t('Option'),
    t('Default price'),
  );
  foreach ($enabled as $rid) {
    $header[] = t('%role price', array(
      '%role' => $roles[$rid],
    ));
  }
  foreach (element_children($form['attributes']) as $key) {
    $row = array();
    $row[] = array(
      'data' => drupal_render($form['attributes'][$key]['aid']) . drupal_render($form['attributes'][$key]['name']),
      'class' => 'attribute',
    );
    if (element_children($form['attributes'][$key]['options'])) {
      foreach (element_children($form['attributes'][$key]['options']) as $oid) {
        $row[] = drupal_render($form['attributes'][$key]['options'][$oid]['name']);
        $row[] = drupal_render($form['attributes'][$key]['options'][$oid]['price']);
        foreach ($enabled as $rid) {
          $row[] = drupal_render($form['attributes'][$key]['options'][$oid]['role_prices'][$rid]);
        }
        $rows[] = $row;
        $row = array(
          '',
        );
      }
      unset($form['attributes'][$key]['default']);
    }
    else {
      $row[] = array(
        'data' => drupal_render($form['attributes'][$key]['default']),
        'colspan' => count($enabled) + 3,
      );
      $rows[] = $row;
    }
    $rows[] = array(
      array(
        'data' => '<hr />',
        'colspan' => count($enabled) + 3,
      ),
    );
  }
  if (count($rows) == 0) {
    $rows[] = array(
      array(
        'data' => t('This product does not have any attributes.'),
        'colspan' => count($enabled) + 3,
      ),
    );
  }
  $output = drupal_render($form['help']) . theme('table', $header, $rows, array(
    'class' => 'product_attributes',
  )) . drupal_render($form);
  return $output;
}

/**
 * Form submit handler to save option prices.
 */
function uc_price_per_role_option_prices_form_submit($form_id, &$form_state) {
  foreach ($form_state['values']['attributes'] as $attribute) {
    if (is_array($attribute['options'])) {
      foreach ($attribute['options'] as $oid => $option) {
        db_query("DELETE FROM {uc_price_per_role_option_prices} WHERE nid = %d AND oid = %d", $form_state['values']['nid'], $oid);
        foreach ($option['role_prices'] as $rid => $price) {
          if (is_numeric($price)) {
            $data = array(
              'nid' => $form_state['values']['nid'],
              'oid' => $oid,
              'rid' => $rid,
              'price' => $price,
            );
            drupal_write_record('uc_price_per_role_option_prices', $data);
          }
        }
      }
    }
  }
  drupal_set_message(t('The option prices have been saved.'));
}

/**
 * Load per-role option price data for the supplied node ID.
 */
function uc_price_per_role_load_option_prices($nid) {
  $prices = array();
  $result = db_query("SELECT oid, rid, price FROM {uc_price_per_role_option_prices} WHERE nid = %d", $nid);
  while ($row = db_fetch_object($result)) {
    $prices[$row->oid][$row->rid] = $row->price;
  }
  return $prices;
}

/**
 * Find the price for the current user from the supplied price array.
 * 
 * Will return FALSE if no price was found.
 */
function uc_price_per_role_find_price($prices) {
  global $user;
  $enabled = variable_get('uc_price_per_role_enabled', array());
  $weights = variable_get('uc_price_per_role_weights', array());
  asort($weights);

  // Check for a chosen role in the price selection block first.
  if (user_access('access price selection block') && $_SESSION['price_role'] && isset($prices[$_SESSION['price_role']])) {
    return $prices[$_SESSION['price_role']];
  }

  // Otherwise, look for a matching role.
  foreach ($weights as $rid => $weight) {
    if (isset($user->roles[$rid]) && $enabled[$rid] && isset($prices[$rid])) {
      return $prices[$rid];
    }
  }
  return FALSE;
}

/**
 * Implementation of hook_block().
 */
function uc_price_per_role_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Pricing selection');
    return $blocks;
  }
  else {
    if ($op == 'view' && $delta == 0 && user_access('access price selection block')) {
      $block = array(
        'subject' => t('Pricing selection'),
        'content' => drupal_get_form('uc_price_per_role_switch_form'),
      );
      return $block;
    }
  }
}

/**
 * Form to allow authorised users to select which role is used for pricing.
 */
function uc_price_per_role_switch_form() {
  $enabled = variable_get('uc_price_per_role_enabled', array());
  $weights = variable_get('uc_price_per_role_weights', array());
  $roles = user_roles();
  asort($weights);
  $options = array(
    '' => 'Default',
  );
  foreach ($weights as $rid => $weight) {
    if ($enabled[$rid]) {
      $options[$rid] = $roles[$rid];
    }
  }
  $form['role'] = array(
    '#type' => 'select',
    '#title' => 'Role',
    '#options' => $options,
    '#default_value' => $_SESSION['price_role'],
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Select pricing role'),
  );
  return $form;
}

/**
 * Form submit handler to save price role selection.
 */
function uc_price_per_role_switch_form_submit($form_id, &$form_state) {
  if (user_access('access price selection block')) {
    $_SESSION['price_role'] = $form_state['values']['role'];
  }
}

/**
 * Implementation of hook_migrate_api().
 */
function uc_price_per_role_migrate_api() {
  return array(
    'api' => 1,
  );
}

Functions

Namesort descending Description
theme_uc_price_per_role_option_prices_form Theme form to edit option prices.
theme_uc_price_per_role_product_prices
theme_uc_price_per_role_settings_form
uc_price_per_role_block Implementation of hook_block().
uc_price_per_role_cart_item Implementation of hook_cart_item().
uc_price_per_role_find_price Find the price for the current user from the supplied price array.
uc_price_per_role_form_alter Implementation of hook_form_alter().
uc_price_per_role_load_option_prices Load per-role option price data for the supplied node ID.
uc_price_per_role_menu Implementation of hook_menu().
uc_price_per_role_menu_alter Implementation of hook_menu_alter().
uc_price_per_role_migrate_api Implementation of hook_migrate_api().
uc_price_per_role_nodeapi Implementation of hook_nodeapi().
uc_price_per_role_option_prices_form Form definition to edit a option prices.
uc_price_per_role_option_prices_form_submit Form submit handler to save option prices.
uc_price_per_role_perm Implementation of hook_perm().
uc_price_per_role_settings_form
uc_price_per_role_settings_form_submit
uc_price_per_role_switch_form Form to allow authorised users to select which role is used for pricing.
uc_price_per_role_switch_form_submit Form submit handler to save price role selection.
uc_price_per_role_theme Implementation of hook_theme().