In Drupal Commerce I want to display multiple prices on a product, regardless of what price the user is entitled to:

  1. The normal price (for people without membership)
  2. The user price
  3. The maximum discount price (for people with the most expensive membership)

I fixed this using a custom rules action and an accompanying custom field formatter (as was confirmed to be the correct way), but I have some doubts regarding the way I implemented it. Below the code:

/** 
 * hook_rules_action_info()
 *
 * Create custom Rules action to save discount value.
 * see callback (multipriceformatter_calculate_full_discount_price) for more info.
 */
function multipriceformatter_rules_action_info() {
  $defaults = array(
    'group' => t('Commerce pricing')
  );

  $actions = array(
    'multipriceformatter_calculate_full_discount_price' => $defaults + array(
      'label' => t('Calculate Full Discount Price'),
      'parameter' => array(
        'line_item_label' => array( // Line item LABEL necessary to store full discount price in SESSION
          'type' => 'text',
          'label' => t('Enter line item label'),
          'description' => t('Line item label - NOT line item id, that one is always empty..'),
        ),
        'calculate_full_discount_price' => array(
          'type' => 'text',
          'label' => t('Full discounted product price'),
          'description' => t('The full discounted price should be calculated in an action BEFORE this action.'.
                              'Then the outputted value is available here.'),
        ),
      ),
    )
  );  
  
  return $actions;
}

/** 
 * Callback as defined by multipriceformatter_rules_action_info()
 * The function name is necessarily the same as the action-name
 *
 ***
 * Store full_discount_price in a session, to access it
 * later on for display
 * see: multipriceformatter_field_formatter_view
 */
function multipriceformatter_calculate_full_discount_price($line_item_label, $calculate_full_discount_price){
  // Use $line_item_label as unique id for the calculated price. Line_item_label equals
  // the product SKU
  
  // There exists some functionality to return variables from this function,
  // but I don't know where these values end up - they're probably only available
  // to Rules UI..
  
  // Also, don't use variable_set/_get methods because that stores into the database, and we need to
  // unset those variables when deleting products/disabling the module/etc. etc.

  // Bottomline: SESSION is the easy way :)
  $_SESSION['discount_prices'][$line_item_label] = $calculate_full_discount_price;  
}

function multipriceformatter_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display){
 // Obtain SESSION['discount_prices'] here to process it further/display it..
}

The point: shouldn't there be a better way to move the discount value than by using SESSIONs?

Comments

tr’s picture

Status: Active » Fixed

The point: shouldn't there be a better way to move the discount value than by using SESSIONs?

Yes. Your action needs to "provide" a variable value, which will then be passed in the context to subsequent rules. For an example, see how the core Rules data_calc action does this. The hook_rules_action_info() for this action is in modules/data.rules.inc, and the implementation is in modules/data.eval.inc.

tr’s picture

Status: Fixed » Closed (fixed)