diff --git a/modules/product_reference/commerce_product_reference.module b/modules/product_reference/commerce_product_reference.module index db63353..299c617 100644 --- a/modules/product_reference/commerce_product_reference.module +++ b/modules/product_reference/commerce_product_reference.module @@ -588,10 +588,111 @@ function commerce_product_reference_field_formatter_info() { 'description' => t('Display the title of the referenced product as plain text.'), 'field types' => array('commerce_product_reference'), ), + 'commerce_product_reference_rendered_product' => array( + 'label' => t('Rendered product'), + 'description' => t('Display the products rendered by the entity system.'), + 'field types' => array('commerce_product_reference'), + 'settings' => array( + 'view_mode' => 'full', + ), + ), ); } /** + * Implements hook_field_formatter_settings_form(). + */ +function commerce_product_reference_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) { + $display = $instance['display'][$view_mode]; + $settings = $display['settings']; + + if ($display['type'] == 'commerce_product_reference_rendered_product') { + $entity_info = entity_get_info('commerce_product'); + $options = array(); + + if (!empty($entity_info['view modes'])) { + foreach ($entity_info['view modes'] as $view_mode => $view_mode_settings) { + $options[$view_mode] = $view_mode_settings['label']; + } + } + + if (count($options) > 1) { + $element['view_mode'] = array( + '#type' => 'select', + '#title' => t('View mode'), + '#options' => $options, + '#default_value' => $settings['view_mode'], + ); + } + } + + return $element; +} + +/** + * Implements hook_field_formatter_settings_summary(). + */ +function commerce_product_reference_field_formatter_settings_summary($field, $instance, $view_mode) { + $display = $instance['display'][$view_mode]; + $settings = $display['settings']; + + $summary = array(); + + if ($display['type'] == 'commerce_product_reference_rendered_product') { + $entity_info = entity_get_info('commerce_product'); + $summary[] = t('View mode: @mode', array('@mode' => isset($entity_info['view modes'][$settings['view_mode']]['label']) ? $entity_info['view modes'][$settings['view_mode']]['label'] : $settings['view_mode'])); + } + + return implode('
', $summary); +} + +/** + * Implements hook_field_formatter_prepare_view(). + */ +function commerce_product_reference_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) { + $product_ids = array(); + + // Collect every possible entity attached to any of the entities. + foreach ($entities as $id => $entity) { + foreach ($items[$id] as $delta => $item) { + if (isset($item['product_id'])) { + $product_ids[] = $item['product_id']; + } + } + } + + if ($product_ids) { + $product_entities = entity_load('commerce_product', $product_ids); + } + else { + $product_entities = array(); + } + + // Iterate through the fieldable products again to attach the loaded data. + foreach ($entities as $id => $entity) { + $rekey = FALSE; + + foreach ($items[$id] as $delta => $item) { + // Check whether the referenced product could be loaded and that the user has access to it. + if (isset($product_entities[$item['product_id']]) && entity_access('view', 'commerce_product', $product_entities[$item['product_id']])) { + // Replace the instance value with the term data. + $items[$id][$delta]['entity'] = $product_entities[$item['product_id']]; + } + // Otherwise, unset the instance value, since the product does not exists or should not be accessible. + else { + unset($items[$id][$delta]); + $rekey = TRUE; + } + } + + if ($rekey) { + // Rekey the items array. + $items[$id] = array_values($items[$id]); + } + } +} + +/** * Implements hook_field_formatter_view(). */ function commerce_product_reference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { @@ -652,6 +753,23 @@ function commerce_product_reference_field_formatter_view($entity_type, $entity, } } break; + + case 'commerce_product_reference_rendered_product': + foreach ($items as $delta => $item) { + // Protect ourselves from recursive rendering. + static $depth = 0; + $depth++; + + if ($depth > 20) { + throw new CommerceProductReferenceRecursiveRenderingException(t('Recursive rendering detected when rendering product (@product_id). Aborting rendering.', array('@product_id' => $item['product_id']))); + } + + $entity = clone $item['entity']; + unset($entity->content); + $result[$delta] = entity_view('commerce_product', array($item['product_id'] => $entity), $display['settings']['view_mode'], $langcode, FALSE); + $depth = 0; + } + break; } return $result; @@ -1238,3 +1356,9 @@ function commerce_product_reference_node_types() { ksort($list); return $list; } + +/** + * Exception thrown when the referenced product display formatter goes into a + * potentially infinite loop. + */ +class CommerceProductReferenceRecursiveRenderingException extends Exception {}