commerce_price_decimals_formatter.module in Commerce Price Decimals Formatter 7
Provides a display formatter for the price field in which you can specify the decimal places are displayed.
File
commerce_price_decimals_formatter.moduleView source
<?php
/**
* @file
* Provides a display formatter for the price field in which you can
* specify the decimal places are displayed.
*/
/**
* Implements hook_field_formatter_info().
*/
function commerce_price_decimals_formatter_field_formatter_info() {
return array(
'commerce_price_decimals_formatter' => array(
'label' => t('Formatted amount with n decimals'),
'field types' => array(
'commerce_price',
),
'settings' => array(
'calculation' => 'calculated_sell_price',
'currencies' => commerce_price_decimals_formatter_get_default_currencies_settings(),
),
),
'commerce_price_decimals_formatter_components' => array(
'label' => t('Formatted amount with n decimals and components'),
'field types' => array(
'commerce_price',
),
'settings' => array(
'calculation' => 'calculated_sell_price',
'currencies' => commerce_price_decimals_formatter_get_default_currencies_settings(),
),
),
);
}
/**
* Implements hook_field_formatter_settings_form().
*/
function commerce_price_decimals_formatter_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'] + field_info_formatter_settings($display['type']);
$form = array();
// Add the default calculation type selection option.
if ($display['type'] != 'commerce_price_decimals_formatter_components') {
$form = commerce_price_field_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
}
// Add the price decimals settings form.
$form = array_merge($form, commerce_price_decimals_formatter_get_settings_form($settings));
return $form;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function commerce_price_decimals_formatter_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'] + field_info_formatter_settings($display['type']);
$summary = array();
// Add the default calculation text to the summary.
if ($display['type'] != 'commerce_price_decimals_formatter_components') {
$summary[] = commerce_price_field_formatter_settings_summary($field, $instance, $view_mode);
}
// Add the currency settings.
$summary = array_merge($summary, commerce_price_decimals_formatter_get_settings_summary($settings));
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_prepare_view().
*
* Rely on the default implementation of prices.
*
* @see commerce_price_field_formatter_prepare_view
*/
function commerce_price_decimals_formatter_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
// Allow other modules to prepare the item values prior to formatting.
foreach (module_implements('commerce_price_field_formatter_prepare_view') as $module) {
$function = $module . '_commerce_price_field_formatter_prepare_view';
$function($entity_type, $entities, $field, $instances, $langcode, $items, $displays);
}
}
/**
* Implements hook_field_formatter_view().
*/
function commerce_price_decimals_formatter_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'] + field_info_formatter_settings($display['type']);
$settings['currencies'] += commerce_price_decimals_formatter_get_default_currencies_settings();
// Loop through each price value in this field.
foreach ($items as $delta => $item) {
// Do not render a price if the amount is NULL (i.e. non-zero empty value).
if (is_null($item['amount'])) {
// TODO: Consider if we should render as N/A or something indicating a
// price was not available as opposed to just leaving a blank.
continue;
}
switch ($display['type']) {
case 'commerce_price_decimals_formatter':
$element[] = array(
'#markup' => commerce_price_decimals_formatter_currency_format($item['amount'], $item['currency_code'], $settings, $entity),
);
break;
case 'commerce_price_decimals_formatter_components':
// Build an array of component display titles and their prices.
$components = array();
$weight = 0;
foreach ($item['data']['components'] as $key => $component) {
$component_type = commerce_price_component_type_load($component['name']);
// Hook in with the Commerce Discount module
if (isset($component['price']['data']['discount_component_title'])) {
$component_type['display_title'] = $component['price']['data']['discount_component_title'];
}
if (empty($components[$component['name']])) {
$components[$component['name']] = array(
'title' => check_plain($component_type['display_title']),
'price' => commerce_price_component_total($item, $component['name']),
'weight' => $component_type['weight'],
);
$weight = max($weight, $component_type['weight']);
}
}
// If there is only a single component and its price equals the field's,
// then remove it and just show the actual price amount.
if (count($components) == 1 && in_array('base_price', array_keys($components))) {
$components = array();
}
// If the i18n_field module is available, we'll use it to translate
// user-configurable field labels.
if (module_exists('i18n_field') && !empty($instance['label'])) {
$instance['label'] = i18n_field_translate_property($instance, 'label');
}
// Add the actual field value to the array.
$components['commerce_price_formatted_amount'] = array(
'title' => check_plain($instance['label']),
'price' => $item,
'weight' => $weight + 1,
);
// Sort the components by weight.
uasort($components, 'drupal_sort_weight');
// Format the prices for display.
foreach ($components as $key => &$component) {
$component['formatted_price'] = commerce_price_decimals_formatter_currency_format($component['price']['amount'], $component['price']['currency_code'], $settings, $entity);
}
$element[$delta] = array(
'#markup' => theme('commerce_price_formatted_components', array(
'components' => $components,
'price' => $item,
)),
);
break;
}
}
return $element;
}
/**
* Returns an array of all available enable currencies and decimals.
*/
function commerce_price_decimals_formatter_get_default_currencies_settings() {
$enable_currencies = commerce_currencies(TRUE);
$currencies = array();
foreach ($enable_currencies as $code => $currency) {
$currencies[$code] = array(
'decimals' => $currency['decimals'],
'force' => FALSE,
'zero' => FALSE,
);
}
return $currencies;
}
/**
* Returns an array of all available settings.
*
* @param array $settings
* Array with display settings.
*
* @return array
* An array of currency arrays keyed with the settings.
*/
function commerce_price_decimals_formatter_get_settings_form($settings) {
// Load defaults settings and append it.
$defaults = commerce_price_decimals_formatter_get_default_currencies_settings();
$settings['currencies'] += $defaults;
$form = array();
$form['currencies'] = array(
'#type' => 'container',
'#tree' => TRUE,
);
foreach ($settings['currencies'] as $code => $currency) {
if (array_key_exists($code, $defaults)) {
$form['currencies'][$code] = array(
'#type' => 'fieldset',
'#title' => t('Settings for @code', array(
'@code' => $code,
)),
'#collapsible' => FALSE,
);
$form['currencies'][$code]['decimals'] = array(
'#type' => 'textfield',
'#title' => t('Number of decimals to show'),
'#default_value' => $settings['currencies'][$code]['decimals'],
'#required' => TRUE,
'#element_validate' => array(
'element_validate_integer',
),
'#size' => 3,
);
$form['currencies'][$code]['force'] = array(
'#type' => 'checkbox',
'#title' => t('Force price decimals'),
'#default_value' => $settings['currencies'][$code]['force'],
);
$form['currencies'][$code]['zero'] = array(
'#type' => 'checkbox',
'#title' => t('Sets zero decimal places when possible'),
'#default_value' => $settings['currencies'][$code]['zero'],
);
}
}
return $form;
}
/**
* Returns an array of all available settings.
*
* @param array $settings
* Array with display settings.
*
* @return array
* An array of currency settings summary.
*/
function commerce_price_decimals_formatter_get_settings_summary($settings) {
// Load defaults settings and append it.
$defaults = commerce_price_decimals_formatter_get_default_currencies_settings();
$settings['currencies'] += $defaults;
$summary = array();
foreach ($settings['currencies'] as $code => $currency) {
if (array_key_exists($code, $defaults)) {
$summary[] = t('Decimals for @code: @force @number.', array(
'@code' => $code,
'@number' => $currency['decimals'],
'@force' => $currency['force'] ? t('Force to') : t('Without force to'),
));
if ($currency['zero']) {
$summary[] = t('Sets zero decimal places when possible');
}
}
}
return $summary;
}
/**
* Formats a price for a particular currency.
*
* @param number $amount
* A numeric price amount value.
* @param string $currency_code
* The three character code of the currency.
* @param array $settings
* Array with display settings.
* @param object $object
* When present, the object to which the price is attached.
* @param boolean $convert
* Boolean indicating whether or not the amount needs to be converted to a
* decimal price amount when formatting.
*
* @return string
* A fully formatted currency.
*/
function commerce_price_decimals_formatter_currency_format($amount, $currency_code, $settings, $object = NULL, $convert = TRUE) {
// First load the currency array.
$currency = commerce_currency_load($currency_code);
// Then convert the price amount to the currency's major unit decimal value.
if ($convert == TRUE) {
$amount = commerce_currency_amount_to_decimal($amount, $currency_code);
}
// Invoke the custom format callback if specified.
if (!empty($currency['format_callback'])) {
return $currency['format_callback']($amount, $currency, $object);
}
// Check the number of decimals.
if (isset($settings['currencies'][$currency_code]['force']) && $settings['currencies'][$currency_code]['force'] == FALSE && $settings['currencies'][$currency_code]['decimals'] < $currency['decimals']) {
$decimals = strlen(substr(strrchr($amount, "."), 1));
if ($decimals < $settings['currencies'][$currency_code]['decimals']) {
$decimals = $settings['currencies'][$currency_code]['decimals'];
}
}
else {
$decimals = $settings['currencies'][$currency_code]['decimals'];
}
if (isset($settings['currencies'][$currency_code]['zero']) && $settings['currencies'][$currency_code]['zero'] == TRUE) {
$zeros = (int) substr(strrchr($amount, "."), 1);
if ($zeros == 0) {
$decimals = 0;
}
}
// Alter currency decimals for a correct round.
$currency['decimals'] = $decimals;
// Format the price as a number.
$price = number_format(commerce_currency_round(abs($amount), $currency), $currency['decimals'], $currency['decimal_separator'], $currency['thousands_separator']);
// Establish the replacement values to format this price for its currency.
$replacements = array(
'@code_before' => $currency['code_placement'] == 'before' ? $currency['code'] : '',
'@symbol_before' => $currency['symbol_placement'] == 'before' ? $currency['symbol'] : '',
'@price' => $price,
'@symbol_after' => $currency['symbol_placement'] == 'after' ? $currency['symbol'] : '',
'@code_after' => $currency['code_placement'] == 'after' ? $currency['code'] : '',
'@negative' => $amount < 0 ? '-' : '',
'@symbol_spacer' => $currency['symbol_spacer'],
'@code_spacer' => $currency['code_spacer'],
);
return trim(t('@code_before@code_spacer@negative@symbol_before@price@symbol_spacer@symbol_after@code_spacer@code_after', $replacements));
}
/**
* Implements hook_views_api().
*/
function commerce_price_decimals_formatter_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'commerce_price_decimals_formatter') . '/includes/views',
);
}
/**
* Implements hook_preprocess_views_view().
*
* When the line item summary and order total area handlers are present on Views
* forms, it is natural for them to appear above the submit buttons that Views
* creates for the form. This hook checks for their existence in the footer area
* and moves them if necessary.
*/
function commerce_price_decimals_formatter_preprocess_views_view(&$vars) {
$view = $vars['view'];
// Determine if the line item summary or order total area handler is present
// on the View.
$has_handler = FALSE;
foreach ($view->footer as $area) {
if ($area instanceof commerce_price_decimals_formatter_handler_area_line_item_summary_decimals || $area instanceof commerce_price_decimals_formatter_handler_area_order_total_decimals) {
$has_handler = TRUE;
}
}
// If one of the handlers is present and the View in question is a form...
if ($has_handler && views_view_has_form_elements($view)) {
// Move the footer area into a row in the View positioned just above the
// form's submit buttons.
$vars['rows']['footer'] = array(
'#type' => 'markup',
'#markup' => $vars['footer'],
'#weight' => 99,
);
$vars['footer'] = '';
}
}