uc_price.inc in Ubercart 6.2
Price handling functions and hooks.
File
uc_store/includes/uc_price.incView source
<?php
/**
* @file
* Price handling functions and hooks.
*/
/**
* The heart of the price modification/displaying system,
* this function handles price alteration, formatting, theming, and caching.
*
* @param $price_info
* Either a simple price to alter/format or an associative array containing
* the following keys:
* - 'price' => the price per item
* - 'qty' => a quantity
* - 'placeholder' => a placeholder string to use as the formatted price
* value in lieu of actually formatting the altered price value
* @param $context
* An associative array containing information about where the function call
* came from. This function will at least add an 'account' key to the array
* if it is not already set with the value being the current user object.
* A revision may also be specified, accepted values follow:
*
* 'revision':
* Default: 'themed'
* - 'original' => Original price value,
* - 'altered' => Original price passed through the alterer(s),
* - 'formatted-original' => Original price passed through the formatter,
* - 'formatted' => Altered price passed through the formatter,
* - 'themed-original' => Formatted original price passed through the
* theme layer,
* - 'themed' => Formatted altered price passed through the theme layer.
*
* @param $options
* An associative array containing options that will be passed through to
* any alteration/formatting/theming functions implemented. A list of accepted
* options follows.
*
* 'sign':
* Default: variable_get('uc_currency_sign', '$')
* The sign to use when formatting this price.
*
* 'sign_after':
* Default: variable_get('uc_sign_after_amount', FALSE)
* If set to TRUE, the sign will come after the price.
*
* 'prec':
* Default: variable_get('uc_currency_prec', 2)
* Precision to round the price to.
*
* 'dec':
* Default: variable_get('uc_currency_dec', '.')
* Decimal separator.
*
* 'thou':
* Default: variable_get('uc_currency_thou', ',')
* Thousand separator.
*
* 'label':
* Default: TRUE
* If set to TRUE, themed prices will include any prefixes and suffixes.
*/
function uc_price($price_info, $context = array(), $options = array()) {
global $user;
// If we're passed just a number for price, we'll set the quantity to 1.
if (is_numeric($price_info)) {
$price_info = array(
'price' => $price_info,
'qty' => 1,
);
}
elseif (!is_array($price_info)) {
$price_info = array(
'price' => 0,
'qty' => 1,
);
}
// Initialize the context.
$context += array(
'revision' => 'themed',
'type' => 'amount',
);
// Clamp to allowed revisions.
$revisions = array(
'original',
'altered',
'formatted-original',
'formatted',
'themed-original',
'themed',
);
if (!in_array($context['revision'], $revisions)) {
$context['revision'] = 'themed';
}
// Calculate the original price.
$original = $price_info['price'] * $price_info['qty'];
// Exit early if the original price was requested.
if ($context['revision'] == 'original') {
return $original;
}
// Get all the active handlers.
$handlers = _uc_price_get_handlers($options);
$formatter = $handlers['formatter'];
// Use the global user if none was passed in.
if (!isset($context['account'])) {
$context['account'] = $user;
}
// Merge any incoming options, giving them precedence.
$options += $handlers['options'];
// Exit early if no alterations are needed.
switch ($context['revision']) {
case 'formatted-original':
return $formatter($original, $options);
case 'themed-original':
return theme('uc_price', $formatter($original, $options), $context, $options);
}
// Alter the price, context, and options.
foreach ($handlers['alterers'] as $alterer) {
$alterer($price_info, $context, $options);
}
$altered = $price_info['price'] * $price_info['qty'];
if ($context['revision'] == 'altered') {
return $altered;
}
// Use a price placeholder if specified.
if (isset($price_info['placeholder'])) {
$formatted = $price_info['placeholder'];
}
else {
$formatted = $formatter($altered, $options);
}
// Return the requested revision.
switch ($context['revision']) {
case 'formatted':
return $formatted;
case 'themed':
return theme('uc_price', $formatted, $context, $options);
}
}
/**
* Return an array of price handler data.
*
* @param $options
* An associative array of options used when building the array with keys:
* - 'rebuild_handlers' => TRUE or FALSE indicating whether we should nuke
* the cache and rebuild the handler data.
* - 'all_handlers' => TRUE or FALSE indicating whether or not to return all
* defined price handlers' alterers or just enabled ones.
* @return
* A structured array of price handler data.
*/
function _uc_price_get_handlers($options = array()) {
static $handlers = array();
// Set default options.
$options += array(
'rebuild_handlers' => FALSE,
'all_handlers' => FALSE,
);
// Get handlers only if we haven't already, or if this is a rebuild.
if (empty($handlers) || $options['rebuild_handlers']) {
// Get the handlers and sort them by weight.
$config = variable_get('uc_price_handler_config', array());
foreach (module_implements('uc_price_handler') as $module) {
// Create a price handler hook data array and merge in sensible defaults.
$hooks[$module] = module_invoke($module, 'uc_price_handler') + array(
'weight' => 0,
'enabled' => TRUE,
);
// Merge any configuration state in.
if (isset($config[$module])) {
$hooks[$module] = $config[$module] + $hooks[$module];
}
// Unset disabled hooks if we're not building the selection form.
if (!$options['all_handlers'] && !$hooks[$module]['enabled']) {
unset($hooks[$module]);
}
}
// Sort the hook data by weight.
uasort($hooks, 'uc_weight_sort');
// Store the raw data for selection form building.
$handlers['hook_data'] = $hooks;
// Store the selected formatter, defaulting to uc_store's implementation.
$formatter = variable_get('uc_price_format_callback', 'uc_store_price_handler_format');
if (function_exists($formatter)) {
$handlers['formatter'] = $formatter;
}
else {
$handlers['formatter'] = 'uc_store_price_handler_format';
}
// Grab all the alter/format callbacks, as well as merging the options.
// This happens in order by weight, so we're kosher.
$handlers['alterers'] = array();
// We set some default options here. We could set them in the uc_store price handler,
// but that means if that handler is disabled, we won't get them merged in.
$handlers['options'] = array(
'sign' => variable_get('uc_currency_sign', '$'),
'sign_after' => variable_get('uc_sign_after_amount', FALSE),
'prec' => variable_get('uc_currency_prec', 2),
'dec' => variable_get('uc_currency_dec', '.'),
'thou' => variable_get('uc_currency_thou', ','),
'label' => TRUE,
);
foreach ($hooks as $hook) {
if (isset($hook['alter']['callback']) && function_exists($hook['alter']['callback'])) {
$handlers['alterers'][] = $hook['alter']['callback'];
}
if (isset($hook['format']['callback']) && function_exists($hook['format']['callback'])) {
$handlers['formatters'][] = $hook['format']['callback'];
}
if (isset($hook['options']) && is_array($hook['options'])) {
$handlers['options'] = $hook['options'] + $handlers['options'];
}
}
}
return $handlers;
}
/**
* Implements hook_uc_price_handler().
*/
function uc_store_uc_price_handler() {
return array(
'alter' => array(
'title' => t('Default price handler'),
'description' => t('The default handler alterer is simply responsible for prefixing various product prices for display.'),
'callback' => 'uc_store_price_handler_alter',
),
'format' => array(
'title' => t('Default price handler'),
'description' => t('The default handler formatter passes prices through a single currency formatter based on the store currency display settings.'),
'callback' => 'uc_store_price_handler_format',
),
);
}
/**
* Default price handler alterer; adds the default prefixes to the various
* product prices when viewing a product node.
*/
function uc_store_price_handler_alter(&$price, &$context, &$options) {
// If a class was specified in the price's context array...
if (isset($context['class']) && is_array($context['class'])) {
// Look for a product price type in the class array and adjust the price
// prefix accordingly.
if (in_array('list', $context['class'])) {
$options['prefixes'][] = t('List Price: ');
}
elseif (in_array('cost', $context['class'])) {
$options['prefixes'][] = t('Cost: ');
}
elseif (in_array('sell', $context['class'])) {
$options['prefixes'][] = t('Price: ');
}
}
}
/**
* Default price handler formatter; formats the price using the store currency
* display settings.
*/
function uc_store_price_handler_format($price, $options) {
$output = '';
// If the value is less than the minimum precision, zero it.
if ($options['prec'] > 0 && abs($price) < 1 / pow(10, $options['prec'])) {
$price = 0;
}
// Force the price to a positive value and add a negative sign if necessary.
if ($price < 0) {
$price = abs($price);
$output .= '-';
}
// Add the currency sign first if specified.
if ($options['sign'] && !$options['sign_after']) {
$output .= $options['sign'];
}
// Format the number, like 1234.567 => 1,234.57
$output .= number_format($price, $options['prec'], $options['dec'], $options['thou']);
// Add the currency sign last if specified.
if ($options['sign'] && $options['sign_after']) {
$output .= $options['sign'];
}
return $output;
}
Functions
Name![]() |
Description |
---|---|
uc_price | The heart of the price modification/displaying system, this function handles price alteration, formatting, theming, and caching. |
uc_store_price_handler_alter | Default price handler alterer; adds the default prefixes to the various product prices when viewing a product node. |
uc_store_price_handler_format | Default price handler formatter; formats the price using the store currency display settings. |
uc_store_uc_price_handler | Implements hook_uc_price_handler(). |
_uc_price_get_handlers | Return an array of price handler data. |