function commerce_product_reference_entity_view in Commerce Core 7
Implements hook_entity_view().
This implementation adds product fields to the content array of an entity on display if the product contains a non-empty product reference field.
File
- modules/
product_reference/ commerce_product_reference.module, line 318 - Defines a field type for referencing products from other entities.
Code
function commerce_product_reference_entity_view($entity, $entity_type, $view_mode, $langcode) {
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
$instances = NULL;
if ($entity_type == 'commerce_line_item' || $entity_type == 'commerce_product') {
// We do not currently support the injection of product fields into the
// display of line items or other products.
return;
}
// Determine if the referencing bundle specifies custom settings
// for the view mode currently displayed.
$bundle_settings = field_bundle_settings($entity_type, $bundle);
if (isset($bundle_settings['view_modes'][$view_mode]) && !empty($bundle_settings['view_modes'][$view_mode]['custom_settings'])) {
$reference_view_mode = $view_mode;
}
else {
$reference_view_mode = 'default';
}
// Don't try to perform the field injection by default.
$perform_field_injection = FALSE;
// Retrieve the real extra fields settings.
$display = field_extra_fields_get_display($entity_type, $bundle, $reference_view_mode);
if (!empty($display)) {
// Loop over the extra fields and see if at least one of the injected field
// is visible.
foreach ($display as $key => $extra_field) {
if (strpos($key, 'product:') !== 0) {
continue;
}
if (!empty($extra_field['visible'])) {
$perform_field_injection = TRUE;
break;
}
}
}
// Stop here if we don't have any field to inject.
if (!$perform_field_injection) {
return;
}
// Resolve the product module path for use in the loop below.
$product_module_path = drupal_get_path('module', 'commerce_product');
// An entity metadata wrapper will be loaded on demand if it is determined
// this entity has a product reference field instance attached to it.
$wrapper = NULL;
// Loop through product reference fields to see if any exist on this entity
// bundle that is either hidden or displayed with the Add to Cart form display
// formatter.
foreach (commerce_info_fields('commerce_product_reference', $entity_type) as $field_name => $field) {
// Load the instances array only if the entity has product reference fields.
if (empty($instances)) {
$instances = field_info_instances($entity_type, $bundle);
}
// If the reference field enables field injection.
if (isset($instances[$field_name]) && !empty($instances[$field_name]['settings']['field_injection'])) {
// If the field is missing a value, continue to next reference field.
if (empty($entity->{$field_name})) {
continue;
}
// Load a wrapper for the entity being viewed.
if (empty($wrapper)) {
$wrapper = entity_metadata_wrapper($entity_type, $entity)
->language($langcode);
}
// Fetch the product reference field value.
$reference_field_value = $wrapper->{$field_name}
->value();
// If this field doesn't reference any products, continue to the next one.
if (empty($reference_field_value)) {
continue;
}
// Find the default product based on the cardinality of the field.
$product = NULL;
if ($field['cardinality'] == 1) {
// The value of single value reference fields is the product object.
$product = $reference_field_value;
}
else {
// Find the default from the array of all the referenced products.
$product = commerce_product_reference_default_product($reference_field_value);
// If the product is disabled, attempt to find one that is active and
// use that as the default product instead.
if (!empty($product) && $product->status == 0) {
foreach ($reference_field_value as $reference_field_item) {
if (!empty($reference_field_item) && $reference_field_item->status != 0) {
$product = $reference_field_item;
break;
}
}
}
}
// If we found a product.
if (!empty($product)) {
// Add the display context for these field to the product.
$product->display_context = array(
'entity_type' => $entity_type,
'entity_id' => $id,
'entity' => $entity,
'view_mode' => $view_mode,
'language' => $langcode,
);
// Determine if the referenced product type specifies custom settings
// for the reference view mode.
$view_mode_settings = field_view_mode_settings('commerce_product', $product->type);
if (!empty($view_mode_settings[$entity_type . '_' . $view_mode]['custom_settings'])) {
$reference_view_mode = $entity_type . '_' . $view_mode;
}
else {
$reference_view_mode = 'default';
}
// Loop through the fields on the referenced product's type.
foreach (field_info_instances('commerce_product', $product->type) as $product_field_name => $product_field) {
if (!isset($product_field['display'][$reference_view_mode])) {
$reference_view_mode = 'default';
}
// Only prepare visible fields.
if (!isset($product_field['display'][$reference_view_mode]['type']) || $product_field['display'][$reference_view_mode]['type'] != 'hidden') {
// Add the product field to the entity's content array.
$content_key = 'product:' . $product_field_name;
$entity->content[$content_key] = field_view_field('commerce_product', $product, $product_field_name, $reference_view_mode, $langcode);
// For multiple value references, add context information so the cart
// form can do dynamic replacement of fields.
if ($field['cardinality'] != 1) {
// Construct an array of classes that will be used to theme and
// target the rendered field for AJAX replacement.
$classes = array(
'commerce-product-field',
drupal_html_class('commerce-product-field-' . $product_field_name),
drupal_html_class('field-' . $product_field_name),
drupal_html_class(implode('-', array(
$entity_type,
$id,
'product',
$product_field_name,
))),
);
// Add an extra class to distinguish empty product fields.
if (empty($entity->content[$content_key])) {
$classes[] = 'commerce-product-field-empty';
}
// Ensure the field's content array has a prefix and suffix key.
$entity->content[$content_key] += array(
'#prefix' => '',
'#suffix' => '',
);
// Add the custom div before and after the prefix and suffix.
$entity->content[$content_key]['#prefix'] = '<div class="' . implode(' ', $classes) . '">' . $entity->content[$content_key]['#prefix'];
$entity->content[$content_key]['#suffix'] .= '</div>';
}
}
}
// Get the extra fields display settings for the current view mode.
$display = field_extra_fields_get_display('commerce_product', $product->type, $reference_view_mode);
// Attach "extra fields" to the bundle representing all the extra fields
// currently attached to products.
foreach (field_info_extra_fields('commerce_product', $product->type, 'display') as $product_extra_field_name => $product_extra_field) {
// Only include extra fields that specify a theme function and that
// are visible on the current view mode.
if (!empty($product_extra_field['theme']) && !empty($display[$product_extra_field_name]['visible'])) {
// Add the product extra field to the entity's content array.
$content_key = 'product:' . $product_extra_field_name;
$entity->content[$content_key] = array(
'#theme' => $product_extra_field['theme'],
'#' . $product_extra_field_name => $product->{$product_extra_field_name},
'#label' => $product_extra_field['label'] . ':',
'#product' => $product,
'#attached' => array(
'css' => array(
$product_module_path . '/theme/commerce_product.theme.css',
),
),
);
// For multiple value references, add context information so the cart
// form can do dynamic replacement of fields.
if ($field['cardinality'] != 1) {
// Construct an array of classes that will be used to theme and
// target the rendered field for AJAX replacement.
$classes = array(
'commerce-product-extra-field',
drupal_html_class('commerce-product-extra-field-' . $product_extra_field_name),
drupal_html_class(implode('-', array(
$entity_type,
$id,
'product',
$product_extra_field_name,
))),
);
// Add an extra class to distinguish empty fields.
if (empty($entity->content[$content_key])) {
$classes[] = 'commerce-product-extra-field-empty';
}
// Ensure the extra field's content array has a prefix and suffix key.
$entity->content[$content_key] += array(
'#prefix' => '',
'#suffix' => '',
);
// Add the custom div before and after the prefix and suffix.
$entity->content[$content_key]['#prefix'] = '<div class="' . implode(' ', $classes) . '">' . $entity->content[$content_key]['#prefix'];
$entity->content[$content_key]['#suffix'] .= '</div>';
}
}
}
}
}
}
}