class CommerceProductInlineEntityFormController in Inline Entity Form 7
@file Defines the inline entity form controller for Commerce Products.
Hierarchy
Expanded class hierarchy of CommerceProductInlineEntityFormController
1 string reference to 'CommerceProductInlineEntityFormController'
- inline_entity_form_entity_info_alter in ./
inline_entity_form.module - Implements hook_entity_info_alter().
File
- includes/
commerce_product.inline_entity_form.inc, line 8 - Defines the inline entity form controller for Commerce Products.
View source
class CommerceProductInlineEntityFormController extends EntityInlineEntityFormController {
public function __construct($entityType, array $settings) {
$this->entityType = $entityType;
$this->settings = $settings + $this
->defaultSettings();
// Convert the old product-specific variation language setting.
if (!empty($settings['use_variation_language']) && empty($settings['override_labels'])) {
$this->settings['override_labels'] = TRUE;
$this->settings['label_singular'] = 'variation';
$this->settings['label_plural'] = 'variations';
unset($this->settings['use_variation_language']);
}
}
/**
* Overrides EntityInlineEntityFormController::css().
*/
public function css() {
return array(
'base' => drupal_get_path('module', 'inline_entity_form') . '/theme/commerce-product.css',
);
}
/**
* Overrides EntityInlineEntityFormController::tableFields().
*/
public function tableFields($bundles) {
$fields = array();
$fields['title'] = array(
'type' => 'property',
'label' => t('Variation title'),
'weight' => 1,
);
$fields['sku'] = array(
'type' => 'property',
'label' => t('SKU'),
'weight' => 2,
);
// If only one product type is allowed, its fields can be used as columns.
if (count($bundles) == 1) {
$bundle = reset($bundles);
foreach (field_info_instances('commerce_product', $bundle) as $field_name => $instance) {
$field = field_info_field($field_name);
// If the product has an imagefield, show it.
if ($field['type'] == 'image') {
// Determine the correct image style to use.
$image_style = 'thumbnail';
if (!empty($instance['widget']['settings']['preview_image_style'])) {
$image_style = $instance['widget']['settings']['preview_image_style'];
}
$fields[$field_name] = array(
'type' => 'field',
'label' => $instance['label'],
'formatter' => 'image',
'settings' => array(
'image_style' => $image_style,
),
'delta' => 0,
'weight' => -10,
);
// Don't add any other imagefields. One is enough.
break;
}
}
// If the type has up to 3 attributes, show them instead of the title field.
$attributes = $this
->attributes($bundle);
if (count($attributes) <= 3) {
$fields['title']['visible'] = FALSE;
foreach ($attributes as $field_name => $attribute) {
$field_type = field_info_field_types($attribute['field']['type']);
// Override the default formatter for taxonomy_term_reference.
if ($field_type['default_formatter'] == 'taxonomy_term_reference_link') {
$field_type['default_formatter'] = 'taxonomy_term_reference_plain';
}
$weight = -3;
$fields[$field_name] = array(
'type' => 'field',
'label' => $attribute['instance']['label'],
'formatter' => $field_type['default_formatter'],
'weight' => ++$weight,
);
}
}
}
$fields['commerce_price'] = array(
'type' => 'field',
'label' => t('Price'),
'formatter' => 'commerce_price_formatted_amount',
'weight' => 99,
);
$fields['status'] = array(
'type' => 'property',
'label' => t('Status'),
'weight' => 100,
);
return $fields;
}
/**
* Overrides EntityInlineEntityFormController::defaultSettings().
*/
public function defaultSettings() {
$defaults = parent::defaultSettings();
$defaults['autogenerate_title'] = FALSE;
return $defaults;
}
/**
* Overrides EntityInlineEntityFormController::settingsForm().
*/
public function settingsForm($field, $instance) {
$form = parent::settingsForm($field, $instance);
$form['autogenerate_title'] = array(
'#type' => 'checkbox',
'#title' => t('Auto generate the product title'),
'#description' => t('This will hide the title input field and generate the title by appending any available attributes to the @entity title.', array(
'@entity' => $instance['entity_type'],
)),
'#default_value' => $this->settings['autogenerate_title'],
);
return $form;
}
/**
* Overrides EntityInlineEntityFormController::entityForm().
*/
public function entityForm($entity_form, &$form_state) {
global $user;
// Get the labels (product / variation).
$labels = $this
->labels();
$product = $entity_form['#entity'];
$extra_fields = field_info_extra_fields('commerce_product', $product->type, 'form');
// Assign newly created products to the current user.
if (empty($product->product_id)) {
$product->uid = $user->uid;
}
$entity_form['product_attributes'] = array(
'#type' => 'fieldset',
'#title' => t('Attributes'),
'#attributes' => array(
'class' => array(
'container-inline',
'ief-product-attributes',
'ief-entity-fieldset',
),
),
);
$entity_form['product_details'] = array(
'#type' => 'fieldset',
'#title' => t('Details'),
'#attributes' => array(
'class' => array(
'ief-product-details',
'ief-entity-fieldset',
),
),
);
$entity_form['sku'] = array(
'#type' => 'textfield',
'#title' => t('SKU'),
'#description' => t('Supply a unique identifier using letters, numbers, hyphens, and underscores. Commas may not be used.'),
'#default_value' => $product->sku,
'#maxlength' => 255,
'#required' => TRUE,
'#fieldset' => 'product_details',
'#weight' => $extra_fields['sku']['weight'],
);
$entity_form['title'] = array(
'#type' => 'textfield',
'#title' => t('@label title', array(
'@label' => drupal_ucfirst($labels['singular']),
)),
'#default_value' => $product->title,
'#maxlength' => 255,
'#required' => TRUE,
'#fieldset' => 'product_details',
// The label might be missing if the Title module has replaced it.
'#weight' => !empty($extra_fields['title']) ? $extra_fields['title']['weight'] : -9,
);
$entity_form['status'] = array(
'#type' => 'radios',
'#title' => t('Status'),
'#default_value' => $product->status,
'#options' => array(
1 => t('Active'),
0 => t('Disabled'),
),
'#required' => TRUE,
'#fieldset' => 'product_details',
'#weight' => $extra_fields['status']['weight'],
);
// Attach fields.
$langcode = entity_language('commerce_product', $product);
field_attach_form('commerce_product', $product, $entity_form, $form_state, $langcode);
// Hide or disable the SKU field if it is auto-generated by Commerce AutoSKU.
if (module_exists('commerce_autosku') && ($settings = commerce_autosku_get_settings($product))) {
$entity_form['sku']['#required'] = FALSE;
$entity_form['sku']['#disabled'] = TRUE;
if ($settings['advanced']['hide_sku']) {
$entity_form['sku']['#access'] = FALSE;
}
else {
$entity_form['sku']['#description'] = t('Will be auto-generated when the form is saved.');
}
}
// Hide the title field if it is auto-generated.
if ($this->settings['autogenerate_title']) {
$entity_form['title']['#required'] = FALSE;
$entity_form['title']['#access'] = FALSE;
// Hide the replacement field added by the Title module as well.
if (module_exists('title')) {
$title_field = title_field_replacement_info('commerce_product', 'title');
if ($title_field) {
$title_field_name = $title_field['field']['field_name'];
if (isset($entity_form[$title_field_name])) {
$entity_form[$title_field_name]['#access'] = FALSE;
$entity_form[$title_field_name]['#required'] = FALSE;
}
}
}
}
// Arrange attributes.
$attributes = $this
->attributes($product->type);
if (empty($attributes)) {
// Hide the fieldset, it will be empty.
$entity_form['product_attributes']['#access'] = FALSE;
}
else {
foreach ($attributes as $field_name => $attribute) {
$entity_form[$field_name]['#fieldset'] = 'product_attributes';
}
}
// Arrange non-attribute fields.
foreach (field_info_instances('commerce_product', $product->type) as $name => $instance) {
$field_name = $instance['field_name'];
$field = field_info_field($field_name);
if (!isset($attributes[$field_name])) {
$entity_form[$field_name]['#fieldset'] = 'product_details';
}
}
$product_type = commerce_product_type_load($product->type);
$product->revision = $product_type['revision'];
return $entity_form;
}
/**
* Overrides EntityInlineEntityFormController::entityFormValidate().
*/
public function entityFormValidate($entity_form, &$form_state) {
$product = $entity_form['#entity'];
$parents_path = implode('][', $entity_form['#parents']);
$product_values = drupal_array_get_nested_value($form_state['values'], $entity_form['#parents']);
$sku = trim($product_values['sku']);
// If the SKU field is enabled, validate it.
if (empty($entity_form['sku']['#disabled'])) {
// Ensure the proposed SKU is unique.
if (!commerce_product_validate_sku_unique($sku, $product->product_id)) {
form_set_error($parents_path . '][sku', t('This SKU is already in use and must be unique. Please supply another value.'));
}
// Validate the SKU for invalid characters.
if (!commerce_product_validate_sku($sku)) {
form_set_error($parents_path . '][sku', t('The SKU %sku contains invalid characters.', array(
'%sku' => $sku,
)));
}
}
// Trim leading and trailing whitespace from the SKU.
drupal_array_set_nested_value($form_state['values'], array_merge($entity_form['#parents'], array(
'sku',
)), $sku);
field_attach_form_validate('commerce_product', $product, $entity_form, $form_state);
}
/**
* Overrides EntityInlineEntityFormController::entityFormSubmit().
*/
public function entityFormSubmit(&$entity_form, &$form_state) {
parent::entityFormSubmit($entity_form, $form_state);
$product = $entity_form['#entity'];
// Show a temporary message to the user for each auto-generated value.
if (empty($product->sku) && module_exists('commerce_autosku') && ($settings = commerce_autosku_get_settings($product))) {
$product->sku = t('Will be auto-generated when the form is saved.');
$product->_remove_sku = TRUE;
}
if (empty($product->title) && $this->settings['autogenerate_title']) {
$product->title = t('Will be auto-generated when the form is saved.');
}
}
/**
* Returns a list of field names that are used as attributes for the given
* product type.
*/
protected function attributes($type) {
// Attributes are tied to the commerce_cart module.
if (!module_exists('commerce_cart')) {
return array();
}
$attributes = array();
// Loop through all the field instances on that product type.
foreach (field_info_instances('commerce_product', $type) as $name => $instance) {
// A field qualifies if it is single value, required and uses a widget
// with a definite set of options. For the sake of simplicity, this is
// currently restricted to fields defined by the options module.
$field = field_info_field($instance['field_name']);
// Get the array of Cart settings pertaining to this instance.
$commerce_cart_settings = commerce_cart_field_instance_attribute_settings($instance);
// If the instance is of a field type that is eligible to function as
// a product attribute field and if its attribute field settings
// specify that this functionality is enabled...
if (commerce_cart_field_attribute_eligible($field) && $commerce_cart_settings['attribute_field']) {
$attributes[$name] = array(
'field' => $field,
'instance' => $instance,
'weight' => $instance['widget']['weight'],
);
}
}
// Sort the fields by weight.
uasort($attributes, 'drupal_sort_weight');
return $attributes;
}
/**
* Overrides EntityInlineEntityFormController::createClone().
*/
public function createClone($entity) {
$cloned_entity = parent::createClone($entity);
$cloned_entity->sku = NULL;
return $cloned_entity;
}
/**
* Overrides EntityInlineEntityFormController::save().
*
* Autogenerates the product title if specified, and then saves the product.
*/
public function save($entity, $context) {
// Remove the temporary message added in entityFormSubmit() so that
// Commerce AutoSKU can do its thing.
if (!empty($entity->_remove_sku)) {
$entity->sku = NULL;
unset($entity->_remove_sku);
}
// Generate the product title. Take the parent entity title as the base.
if ($this->settings['autogenerate_title']) {
$entity->title = entity_label($context['parent_entity_type'], $context['parent_entity']);
$attributes = $this
->attributes($entity->type);
if (!empty($attributes)) {
$wrapper = entity_metadata_wrapper('commerce_product', $entity);
$attribute_values = array();
foreach ($attributes as $field_name => $attribute) {
$attribute_label = $wrapper->{$field_name}
->label();
if (!empty($attribute_label)) {
$attribute_values[] = $attribute_label;
}
}
if (!empty($attribute_values)) {
$entity->title .= ' (' . implode(', ', $attribute_values) . ')';
}
}
}
entity_save('commerce_product', $entity);
}
/**
* Overrides EntityInlineEntityFormController::delete().
*
* Disables products that can't be deleted (because they are already
* referenced from a line item, or for some other reason), deletes the rest.
*/
public function delete($ids, $context) {
$products = entity_load('commerce_product', $ids);
foreach ((array) $products as $product_id => $product) {
if (!commerce_product_can_delete($product)) {
$product->status = FALSE;
entity_save('commerce_product', $product);
unset($products[$product_id]);
}
}
// When the parent entity is being removed, we don't want to trigger the
// products deletion right away, otherwise the magic that happens in
// commerce_product_reference_commerce_product_delete() will ultimately
// trigger an entity_save() on the parent entity that is about to be
// deleted from the database.
drupal_register_shutdown_function('commerce_product_delete_multiple', array_keys($products));
}
}