Define extra fields (display) in code for Drupal Commerce products with auto AJAX handling and product+product node types handling

Today I had the challenge to add some extra (programatically calculated) fields to show in ‎Drupal Commerce‎ product display nodes. In our specific case it was a "base price" that should be shown additionally to calculated SALE prices.

First approach using hook_field_extra_fields

hook_field_extra_fields seemed to be a very good solutions and with ‎Extrafield Views Integration‎ there was a good module solution to expose these values to views.

Everything worked fine except the fact that the product selection (options) in the product display did not correctly replace the field when changing values (AJAX update functionality).
After investigating I found out that commerce_cart_add_to_cart_form_attributes_refresh only handles extra fields containing a "theme" attribute:

  1. // Only include extra fields that specify a theme function and that
  2.       // are visible on the current view mode.
  3.       if (!empty($product_extra_field['theme']) &&
  4.         !empty($display[$product_extra_field_name]['visible'])) {
  5.         // ...

Creating a workaround without final success

So I added that attribute and a custom theme function. Now the function handled the field via AJAX but I was still missing the field display in the product node type configuration (only had it available in the product itself).

Use HOOK_commerce_product_add_extra_fields_alter to be happy!

I went on investigating and finally found a better and really handy solution in this issue: ‎Add hook_commerce_product_add_extra_fields_alter or similar to replace hook_field_extra_fields_alter functionality [#2104341]
Using HOOK_commerce_product_add_extra_fields_alter is very clean (patch from the issue is required!) because it handles our extra fields like native products extra fields (like "sku" for example). AJAX handling, adding the field to product and product display, etc. is done automatically.

This solution made it possible to add arbitrary extra fields to the product and product display with just some lines of code.

Code examples

Feel free to modify the example / POC from below for your own requirements:

  1. /**
  2.  * Implements HOOK_commerce_product_add_extra_fields_alter().
  3.  * @See <a href="https://www.drupal.org/node/2104341<br />
  4. " title="https://www.drupal.org/node/2104341<br />
  5. ">https://www.drupal.org/node/2104341<br />
  6. </a> * !! IMPORTANT: Requires commerce_product patch #3 from <a href="https://www.drupal.org/node/2104341" title="https://www.drupal.org/node/2104341">https://www.drupal.org/node/2104341</a> !!
  7.  *
  8.  */
  9. function MY_MODULE_commerce_product_add_extra_fields_alter(&$extra) {
  10.   // We define our product (type "coupon") extra field in this alter function because HOOK_field_extra_fields is not being
  11.   // recognized by commerce_product_reference.
  12.   //
  13.   // We need that to show and handle the field in the product itself but also in the product display and especially its automatical AJAX handling for product selection.
  14.   // Only for product type coupon:
  15.   $extra['commerce_product']['coupon']['display']['commerce_product_coupon_regular_price'] = array(
  16.     'label' => t('Regular price'),
  17.     'description' => t('Displays the regular price. Important: This field is only displayed for products with SALE option currently active!'),
  18.     /*
  19.      * Specify theme function for commerce_product_coupon_regular_price extra_field.
  20.      * This is required because "commerce_cart_add_to_cart_form_attributes_refresh()" only adds extra_fields
  21.      * automatically to the AJAX handling (product switch) which provide a "theme" callback / parameter!
  22.      */
  23. //    'theme' => 'MY_MODULE_extra_field_commerce_product_coupon_regular_price',
  24.     'weight' => 10,
  25.   );
  26. }
  27.  
  28. /**
  29.  * Implements HOOK_theme
  30.  */
  31. function MY_MODULE_theme() {
  32.   // #webksde#JP20150805: Add custom theme function for the extra_field.
  33.   //  Theme function for commerce_product_coupon_regular_price extra_field.
  34.   // * This is required because "commerce_cart_add_to_cart_form_attributes_refresh()" only adds extra_fields
  35.   // * automatically to the AJAX handling (product switch) which provide a "theme" callback / parameter!
  36.   return array('MY_MODULE_extra_field_commerce_product_coupon_regular_price' => array());
  37. }
  38.  
  39. /**
  40.  * Theme function for commerce_product_coupon_regular_price extra_field.
  41.  * This is required because "commerce_cart_add_to_cart_form_attributes_refresh()" only adds extra_fields
  42.  * automatically to the AJAX handling (product switch) which provide a "theme" callback / parameter!
  43.  */
  44. function theme_MY_MODULE_extra_field_commerce_product_coupon_regular_price($variables) {
  45.   return drupal_render($variables['commerce_product_coupon_regular_price']);
  46. }
  47.  
  48. /**
  49.  * Implements HOOK_entity_load().
  50.  *
  51.  * @param type $entities
  52.  * @param type $type
  53.  */
  54. function MY_MODULE_entity_load($entities, $type) {
  55.   // Add a normal price field containing the regular price.
  56.   // Attach the field values to the entity.
  57.   if ($type == 'commerce_product') {
  58.     foreach ($entities as $entity) {
  59.       if($entity->type == 'coupon') {
  60.         // Is a coupon product type!
  61.         $regular_price = _MY_MODULE_commerce_product_regular_price_field_extra_display($entity);
  62.         $entity->commerce_product_coupon_regular_price = array('#markup' => $regular_price);
  63.       }
  64.     }
  65.   }
  66. }
  67.  
  68. // + the concrete implementation of the normal price calculation

Views integration finally

To make the values available in views without writing an own views handler, you may simply install ‎Extrafield Views Integration‎ and add a callback function like this:

  1. /**
  2.  * Implements HOOK_field_extra_fields().
  3.  */
  4. function MY_MODULE_field_extra_fields_alter(&$info) {
  5.   // Add a callback function to make the values available in views via ‎Extrafield Views Integration‎:
  6.   $info['commerce_product']['coupon']['display']['commerce_product_coupon_regular_price']['callback'] = '_MY_MODULE_commerce_product_regular_price_field_extra_display';
  7.   $info['node']['product_display']['display']['product:commerce_product_coupon_regular_price']['callback'] = '_MY_MODULE_commerce_product_regular_price_field_extra_display';
  8. }

Kommentare

Kommentar hinzufügen

Der Inhalt dieses Feldes wird nicht öffentlich zugänglich angezeigt. Wenn Sie ein zulässiges Avatar mit Ihrer E-Mail-Adresse verknüpft haben, wird dieses als Avatar verwendet.

Weitere Informationen über Formatierungsoptionen

Aktualisieren Geben Sie die Zeichen ein, die Sie im Bild sehen. Geben Sie die im Bild dargestellten Zeichen ein; wenn Sie diese nicht lesen können, senden Sie das Formular ohne Eingabe ab, um ein neues Bild zu generieren. Groß-/Kleinschreibung wird nicht beachtet.  Switch to audio verification.