commerce_price_savings_formatter.module in Commerce Price Savings Formatter 7
Adds a display formatter for the price field showing the amount of savings.
File
commerce_price_savings_formatter.moduleView source
<?php
// $Id$
/**
* @file
* Adds a display formatter for the price field showing the amount of savings.
*/
/**
* Implements hook_hook_info().
*/
function commerce_price_savings_formatter_hook_info() {
$hooks = array(
'commerce_price_savings_formatter_prices_alter' => array(
'group' => 'field',
),
);
return $hooks;
}
/**
* Implements hook_field_formatter_info().
*/
function commerce_price_savings_formatter_field_formatter_info() {
return array(
'commerce_price_savings_formatter_formatter' => array(
'label' => t('Formatted amount with savings'),
'field types' => array(
'commerce_price',
),
'settings' => array(
'calculation' => 'calculated_sell_price',
'prices' => array(
'list',
'price',
'savings',
),
'savings' => 'both',
'show_labels' => TRUE,
),
),
'commerce_price_savings_formatter_inline' => array(
'label' => t('Formatted amount with savings (inline)'),
'field types' => array(
'commerce_price',
),
'settings' => array(
'calculation' => 'calculated_sell_price',
'prices' => array(
'list',
'price',
),
'savings' => 'percentage',
'show_labels' => FALSE,
),
),
);
}
/**
* Implements hook_field_formatter_settings_form().
*/
function commerce_price_savings_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']);
// Add the default calculation type selection option.
$form = commerce_price_field_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
// Add the price display settings form.
$form['prices'] = array(
'#type' => 'checkboxes',
'#title' => t('Prices to display'),
'#options' => array(
'list' => t('List price'),
'price' => t('Price'),
'savings' => t('You save'),
),
'#default_value' => $settings['prices'],
);
$form['savings'] = array(
'#type' => 'radios',
'#title' => t('Savings display method'),
'#options' => array(
'amount' => t('The amount saved'),
'percentage' => t('The percentage saved'),
'both' => t('Both the amount and percentage saved'),
),
'#default_value' => $settings['savings'],
);
$form['show_labels'] = array(
'#type' => 'checkbox',
'#title' => t('Show Price Labels'),
'#default_value' => $settings['show_labels'],
);
return $form;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function commerce_price_savings_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.
$summary[] = commerce_price_field_formatter_settings_summary($field, $instance, $view_mode);
// Add rows for specific settings.
$prices = array(
'list' => t('List price'),
'price' => t('Price'),
'savings' => t('You save'),
);
$prices_shown = implode(', ', array_intersect_key($prices, drupal_map_assoc(array_values($settings['prices']))));
if (!empty($prices_shown)) {
$summary[] = t('Showing: !prices', array(
'!prices' => $prices_shown,
));
}
else {
$summary[] = t('Not showing any prices.');
}
if (!empty($settings['show_labels'])) {
$summary[] = t('Labels shown');
}
else {
$summary[] = t('No labels');
}
switch ($settings['savings']) {
case 'amount':
$summary[] = t('Savings displayed as the amount.');
break;
case 'percentage':
$summary[] = t('Savings displayed as the percentage.');
break;
case 'both':
$summary[] = t('Savings displayed as the amount and percentage.');
break;
}
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_prepare_view().
*/
function commerce_price_savings_formatter_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
commerce_price_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, $items, $displays);
}
/**
* Implements hook_field_formatter_view().
*/
function commerce_price_savings_formatter_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'] + field_info_formatter_settings($display['type']);
$tax_module_exists = module_exists('commerce_tax');
// Theme the display of the price based on the display type.
if (in_array($display['type'], array(
'commerce_price_savings_formatter_formatter',
'commerce_price_savings_formatter_inline',
))) {
// exit if no display prices
if (empty($settings['prices'])) {
return $element;
}
// remove prices not selected
$settings['prices'] = array_filter($settings['prices']);
// exit if no prices selected
if (empty($settings['prices'])) {
return $element;
}
// store prices count
$prices_count = count($settings['prices']);
// determine if labels are shown
$show_labels = !empty($settings['show_labels']);
// determine theme
$item_theme = $display['type'];
// Loop through each price value in this field.
foreach ($items as $delta => $item) {
$difference = 0;
$base_price_component = commerce_price_component_total($item, 'base_price');
$base_currency = commerce_currency_load($base_price_component['currency_code']);
if ($base_price_component) {
// calculate included tax amount on base amount
$included_tax_amount = 0;
foreach ($item['data']['components'] as $component) {
if (!empty($component['included']) && !empty($component['price']['data']['tax_rate'])) {
$included_tax_amount += commerce_currency_convert($component['price']['amount'], $component['price']['currency_code'], $base_price_component['currency_code']);
}
}
$base_price_component['amount'] += $included_tax_amount;
// Calculate the difference between the base price and calculated price.
$difference = $base_price_component['amount'] - commerce_currency_convert($item['amount'], $item['currency_code'], $base_price_component['currency_code']);
// Get decimal value for rounding
$difference_decimal = commerce_currency_amount_to_decimal($difference, $base_price_component['currency_code']);
// Round per currency rounding_step
$difference_decimal = commerce_currency_round($difference_decimal, $base_currency);
// Update difference amount
$difference = commerce_currency_decimal_to_amount($difference_decimal, $base_price_component['currency_code']);
}
// determine price direction
$price_direction = $difference > 0 ? 'down' : ($difference < 0 ? 'up' : 'unchanged');
// format prices
$formatted_prices = array();
foreach ($settings['prices'] as $price_type) {
switch ($price_type) {
case 'list':
// Only show the list price if the current price is lower.
if ($difference > 0 || $prices_count == 1) {
$formatted_prices[$price_type] = array(
'label' => t('List price'),
'amount' => $base_price_component['amount'],
'currency_code' => $base_price_component['currency_code'],
'formatted' => commerce_currency_format($base_price_component['amount'], $base_price_component['currency_code'], $entity),
);
}
break;
case 'price':
$formatted_prices[$price_type] = array(
'label' => t('Price'),
'amount' => $item['amount'],
'currency_code' => $item['currency_code'],
'formatted' => commerce_currency_format($item['amount'], $item['currency_code'], $entity),
);
break;
case 'savings':
// Only show the savings if the current price is lower than the list
// price; i.e. if there actually are savings.
if ($difference > 0) {
$percentage = round($difference / $base_price_component['amount'] * 100) . '%';
$formatted_prices[$price_type] = array(
'label' => t('You save'),
'amount' => $difference,
'currency_code' => $item['currency_code'],
'formatted' => commerce_currency_format($difference, $item['currency_code'], $entity),
);
if (!empty($base_price_component['amount'])) {
$difference_percent = $difference / $base_price_component['amount'];
$formatted_prices[$price_type]['percent'] = array(
'value' => $difference_percent,
'formatted' => round($difference_percent * 100) . '%',
);
}
}
break;
}
}
// /settings price type loop
// allow other to alter the formatted prices
$context = array(
'settings' => $settings,
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
'display' => $display,
);
drupal_alter('commerce_price_savings_formatter_prices', $formatted_prices, $context);
// set savings
if (!empty($formatted_prices['savings']) && !empty($settings['prices']['savings'])) {
switch ($settings['savings']) {
case 'percentage':
if (!empty($formatted_prices['savings']['percent']['formatted'])) {
$formatted_prices['savings']['formatted'] = $formatted_prices['savings']['percent']['formatted'];
}
else {
$formatted_prices['savings']['formatted'] = '';
}
break;
case 'both':
if (!empty($formatted_prices['savings']['percent']['formatted'])) {
$formatted_prices['savings']['formatted'] .= ' (' . $formatted_prices['savings']['percent']['formatted'] . ')';
}
break;
}
}
// build price elements only formatted values
$price_elements = array();
foreach ($formatted_prices as $price_type => $price_data) {
// build prices array with rendered price
if (isset($price_data['formatted'])) {
$price_elements[$price_type] = array(
'#markup' => $price_data['formatted'],
);
// add label
if ($show_labels) {
$price_elements[$price_type]['#price_label'] = !empty($price_data['label']) ? $price_data['label'] : '';
}
}
}
$element[$delta] = array(
'#theme' => $item_theme,
'#prices' => $price_elements,
'#price_direction' => $price_direction,
'#attached' => array(
'css' => array(
drupal_get_path('module', 'commerce_price_savings_formatter') . '/theme/commerce_price_savings_formatter.css',
),
),
);
}
// /item loop
}
// /type switch
return $element;
}
/**
* Implements hook_theme().
*/
function commerce_price_savings_formatter_theme() {
return array(
'commerce_price_savings_formatter_formatter' => array(
'variables' => array(
'prices' => array(),
'price_direction' => NULL,
),
),
'commerce_price_savings_formatter_inline' => array(
'variables' => array(
'prices' => array(),
'price_direction' => NULL,
),
),
);
}
/**
* Theme callback: display prices in a table.
*/
function theme_commerce_price_savings_formatter_formatter($vars) {
// Build an array of table rows based on the prices passed in.
$rows = array();
// exit if no prices
if (empty($vars['prices'])) {
return '';
}
// store prices count
$prices_count = count($vars['prices']);
// extract price direction
$price_direction = !empty($vars['price_direction']) ? $vars['price_direction'] : 'unchanged';
// build rows
foreach ($vars['prices'] as $key => $price_element) {
$row_data = array();
// add label
if (isset($price_element['#price_label'])) {
if (!empty($price_element['#price_label'])) {
$label = t('@label:', array(
'@label' => $price_element['#price_label'],
));
}
else {
$label = '';
}
$row_data[] = array(
'data' => $label,
'class' => array(
'price-label',
),
);
}
// add price
$row_data[] = array(
'data' => drupal_render($price_element),
'class' => array(
'price-amount',
),
);
$rows[] = array(
'data' => $row_data,
'class' => array(
'commerce-price-savings-formatter-' . $key,
),
);
}
return theme('table', array(
'rows' => $rows,
'attributes' => array(
'class' => array(
'commerce-price-savings-formatter-prices',
'commerce-price-savings-formatter-prices-count-' . $prices_count,
'commerce-price-savings-formatter-prices-' . $price_direction,
),
),
));
}
/**
* Theme callback: display prices as a list.
*/
function theme_commerce_price_savings_formatter_inline($vars) {
// Build an array of table rows based on the prices passed in.
$rows = array();
// exit if no prices
if (empty($vars['prices'])) {
return '';
}
// store prices count
$prices_count = count($vars['prices']);
// extract price direction
$price_direction = !empty($vars['price_direction']) ? $vars['price_direction'] : 'unchanged';
// build rows individually
$price_row = array();
$label_row = array();
foreach ($vars['prices'] as $key => $price_element) {
$row_data = array();
// add label
if (isset($price_element['#price_label'])) {
if (!empty($price_element['#price_label'])) {
$label = t('@label', array(
'@label' => $price_element['#price_label'],
));
}
else {
$label = '';
}
$label_row[$key] = array(
'data' => '<span class="price-label">' . $label . '</span>',
'class' => array(
'commerce-price-savings-formatter-' . $key,
),
);
}
// add price
$price_row[$key] = array(
'data' => '<span class="price-amount">' . drupal_render($price_element) . '</span>',
'class' => array(
'commerce-price-savings-formatter-' . $key,
),
);
}
// fill out label row
if (!empty($label_row) && count($label_row) != count($price_row)) {
foreach ($price_row as $key => $price_cell) {
if (!isset($label_row[$key])) {
$label_row[$key] = '';
}
}
}
// combine rows
$rows = array(
array(
'data' => $price_row,
'class' => array(
'commerce-price-savings-formatter-price-row',
),
),
array(
'data' => $label_row,
'class' => array(
'commerce-price-savings-formatter-label-row',
),
),
);
return theme('table', array(
'rows' => $rows,
'attributes' => array(
'class' => array(
'inline',
'commerce-price-savings-formatter-prices',
'commerce-price-savings-formatter-prices-inline',
'commerce-price-savings-formatter-prices-count-' . $prices_count,
'commerce-price-savings-formatter-prices-' . $price_direction,
),
),
));
}
Functions
Name![]() |
Description |
---|---|
commerce_price_savings_formatter_field_formatter_info | Implements hook_field_formatter_info(). |
commerce_price_savings_formatter_field_formatter_prepare_view | Implements hook_field_formatter_prepare_view(). |
commerce_price_savings_formatter_field_formatter_settings_form | Implements hook_field_formatter_settings_form(). |
commerce_price_savings_formatter_field_formatter_settings_summary | Implements hook_field_formatter_settings_summary(). |
commerce_price_savings_formatter_field_formatter_view | Implements hook_field_formatter_view(). |
commerce_price_savings_formatter_hook_info | Implements hook_hook_info(). |
commerce_price_savings_formatter_theme | Implements hook_theme(). |
theme_commerce_price_savings_formatter_formatter | Theme callback: display prices in a table. |
theme_commerce_price_savings_formatter_inline | Theme callback: display prices as a list. |