diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php index 7407ad2d43..8018dc597b 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php @@ -196,24 +196,27 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen * The selected variation. */ protected function selectVariationFromUserInput(array $variations, array $user_input) { - $current_variation = reset($variations); + $selected_variation = NULL; if (!empty($user_input)) { $attributes = $user_input['attributes']; + $first_value = current($attributes); + $first_key = current(array_keys($attributes)); foreach ($variations as $variation) { - $match = TRUE; + $values = []; foreach ($attributes as $field_name => $value) { - if ($variation->getAttributeValueId($field_name) != $value) { - $match = FALSE; + $values[$field_name] = $variation->getAttributeValueId($field_name); + if ($first_key == $field_name && $values[$field_name] === $first_value) { + $selected_variation = $selected_variation ?: $variation; } } - if ($match) { - $current_variation = $variation; + if ($attributes === $values) { + $selected_variation = $variation; break; } } } - return $current_variation; + return $selected_variation ?: reset($variations); } /** @@ -228,14 +231,14 @@ protected function selectVariationFromUserInput(array $variations, array $user_i * The attribute information, keyed by field name. */ protected function getAttributeInfo(ProductVariationInterface $selected_variation, array $variations) { - $attributes = []; + $attributes = $values = []; $field_definitions = $this->attributeFieldManager->getFieldDefinitions($selected_variation->bundle()); $field_map = $this->attributeFieldManager->getFieldMap($selected_variation->bundle()); $field_names = array_column($field_map, 'field_name'); $index = 0; foreach ($field_names as $field_name) { /** @var \Drupal\commerce_product\Entity\ProductAttributeInterface $attribute_type */ - $attribute_type = $this->attributeStorage->load(substr($field_name, 10)); + $attribute_type = $this->attributeStorage->load($field_map[$index]['attribute_id']); $field = $field_definitions[$field_name]; $attributes[$field_name] = [ 'field_name' => $field_name, @@ -257,9 +260,17 @@ protected function getAttributeInfo(ProductVariationInterface $selected_variatio }; } - $attributes[$field_name]['values'] = $this->getAttributeValues($variations, $field_name, $callback); + $value = $this->getAttributeValues($variations, $field_name, $callback); + if (!isset($values[$field_name])) { + $values[$field_name] = $value; + } + elseif (!in_array($values[$field_name], $value)) { + $values[$field_name] += $value; + } + $attributes[$field_name]['values'] = $values[$field_name]; $index++; } + // Filter out attributes with no values. $attributes = array_filter($attributes, function ($attribute) { return !empty($attribute['values']); diff --git a/modules/product/src/ProductAttributeFieldManager.php b/modules/product/src/ProductAttributeFieldManager.php index 22f38a780b..44ef6d6062 100644 --- a/modules/product/src/ProductAttributeFieldManager.php +++ b/modules/product/src/ProductAttributeFieldManager.php @@ -143,11 +143,13 @@ protected function buildFieldMap() { $handler_settings = $definition->getSetting('handler_settings'); $component = $form_display->getComponent($field_name); - $field_map[$bundle][] = [ - 'attribute_id' => reset($handler_settings['target_bundles']), - 'field_name' => $field_name, - 'weight' => $component ? $component['weight'] : 0, - ]; + foreach ($handler_settings['target_bundles'] as $id => $target_bundle) { + $field_map[$bundle][] = [ + 'attribute_id' => $target_bundle, + 'field_name' => $field_name, + 'weight' => $component ? $component['weight'] : 0, + ]; + } } if (!empty($field_map[$bundle])) { @@ -215,18 +217,16 @@ public function createField(ProductAttributeInterface $attribute, $variation_typ */ public function canDeleteField(ProductAttributeInterface $attribute, $variation_type_id) { $field_name = $this->buildFieldName($attribute); - // Prevent an EntityQuery crash by first confirming the field exists. - $field = FieldConfig::loadByName('commerce_product_variation', $variation_type_id, $field_name); - if (!$field) { - throw new \InvalidArgumentException(sprintf('Could not find the attribute field "%s" for attribute "%s".', $field_name, $attribute->id())); + if (FieldConfig::loadByName('commerce_product_variation', $variation_type_id, $field_name)) { + $query = $this->entityTypeManager->getStorage('commerce_product_variation')->getQuery() + ->condition('type', $variation_type_id) + ->exists($field_name) + ->range(0, 1); + $result = $query->execute(); } - $query = $this->entityTypeManager->getStorage('commerce_product_variation')->getQuery() - ->condition('type', $variation_type_id) - ->exists($field_name) - ->range(0, 1); - $result = $query->execute(); - return empty($result); + // To prevent crashes just do not confirm deletion if field does not exist. + return isset($result) ? empty($result) : FALSE; } /**