From 18694ba9954621ada4dda26b7fd93e8565b63a9d Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Mon, 20 Mar 2017 16:00:35 +0000 Subject: [PATCH 01/24] Issue #2860840 by mgoncalves, Regnoy, mglaman, bojanz, GoZ, vasike: Product variantion add to cart not translated. --- modules/order/src/Entity/OrderItem.php | 7 ++-- modules/product/src/Entity/Product.php | 31 ++------------ modules/product/src/Entity/ProductVariation.php | 16 +++++--- .../Field/FieldFormatter/AddToCartFormatter.php | 4 +- .../ProductVariationAttributesWidget.php | 4 +- .../FieldWidget/ProductVariationWidgetBase.php | 5 +++ modules/product/src/ProductLazyBuilders.php | 8 +++- src/Entity/CommerceContentEntityBase.php | 48 ++++++++++++++++++++++ src/Entity/CommerceContentEntityInterface.php | 23 +++++++++++ 9 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 src/Entity/CommerceContentEntityBase.php create mode 100644 src/Entity/CommerceContentEntityInterface.php diff --git a/modules/order/src/Entity/OrderItem.php b/modules/order/src/Entity/OrderItem.php index 0210f1ae9..c2dcb3231 100644 --- a/modules/order/src/Entity/OrderItem.php +++ b/modules/order/src/Entity/OrderItem.php @@ -2,9 +2,9 @@ namespace Drupal\commerce_order\Entity; +use Drupal\commerce\Entity\CommerceContentEntityBase; use Drupal\commerce_order\Adjustment; use Drupal\commerce_price\Price; -use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -46,7 +46,7 @@ * field_ui_base_route = "entity.commerce_order_item_type.edit_form", * ) */ -class OrderItem extends ContentEntityBase implements OrderItemInterface { +class OrderItem extends CommerceContentEntityBase implements OrderItemInterface { use EntityChangedTrait; @@ -68,7 +68,8 @@ public function getOrderId() { * {@inheritdoc} */ public function getPurchasedEntity() { - return $this->get('purchased_entity')->entity; + $purchased_entity = $this->getTranslatedReferencedEntities('purchased_entity'); + return reset($purchased_entity); } /** diff --git a/modules/product/src/Entity/Product.php b/modules/product/src/Entity/Product.php index 260135e59..38e8669b7 100644 --- a/modules/product/src/Entity/Product.php +++ b/modules/product/src/Entity/Product.php @@ -3,7 +3,7 @@ namespace Drupal\commerce_product\Entity; use Drupal\user\UserInterface; -use Drupal\Core\Entity\ContentEntityBase; +use Drupal\commerce\Entity\CommerceContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -69,7 +69,7 @@ * field_ui_base_route = "entity.commerce_product_type.edit_form", * ) */ -class Product extends ContentEntityBase implements ProductInterface { +class Product extends CommerceContentEntityBase implements ProductInterface { use EntityChangedTrait; @@ -122,8 +122,7 @@ public function setCreatedTime($timestamp) { * {@inheritdoc} */ public function getStores() { - $stores = $this->get('stores')->referencedEntities(); - return $this->ensureTranslations($stores); + return $this->getTranslatedReferencedEntities('stores'); } /** @@ -198,8 +197,7 @@ public function getVariationIds() { * {@inheritdoc} */ public function getVariations() { - $variations = $this->get('variations')->referencedEntities(); - return $this->ensureTranslations($variations); + return $this->getTranslatedReferencedEntities('variations'); } /** @@ -271,27 +269,6 @@ public function getDefaultVariation() { } /** - * Ensures that the provided entities are in the current entity's language. - * - * @param \Drupal\Core\Entity\ContentEntityInterface[] $entities - * The entities to process. - * - * @return \Drupal\Core\Entity\ContentEntityInterface[] - * The processed entities. - */ - protected function ensureTranslations(array $entities) { - $langcode = $this->language()->getId(); - foreach ($entities as $index => $entity) { - /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ - if ($entity->hasTranslation($langcode)) { - $entities[$index] = $entity->getTranslation($langcode); - } - } - - return $entities; - } - - /** * {@inheritdoc} */ public function postSave(EntityStorageInterface $storage, $update = TRUE) { diff --git a/modules/product/src/Entity/ProductVariation.php b/modules/product/src/Entity/ProductVariation.php index 08b878eb8..234beb9c9 100644 --- a/modules/product/src/Entity/ProductVariation.php +++ b/modules/product/src/Entity/ProductVariation.php @@ -2,9 +2,9 @@ namespace Drupal\commerce_product\Entity; +use Drupal\commerce\Entity\CommerceContentEntityBase; use Drupal\commerce_price\Price; use Drupal\Core\Cache\Cache; -use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -55,7 +55,7 @@ * field_ui_base_route = "entity.commerce_product_variation_type.edit_form", * ) */ -class ProductVariation extends ContentEntityBase implements ProductVariationInterface { +class ProductVariation extends CommerceContentEntityBase implements ProductVariationInterface { use EntityChangedTrait; @@ -89,7 +89,8 @@ public function toUrl($rel = 'canonical', array $options = []) { * {@inheritdoc} */ public function getProduct() { - return $this->get('product_id')->entity; + $product = $this->getTranslatedReferencedEntities('product_id'); + return reset($product); } /** @@ -277,7 +278,10 @@ public function getAttributeValues() { foreach ($this->getAttributeFieldNames() as $field_name) { $field = $this->get($field_name); if (!$field->isEmpty()) { - $attribute_values[$field_name] = $field->entity; + /** @var \Drupal\commerce_product\Entity\ProductAttributeValueInterface $entity */ + $entity = $field->entity; + $attribute_value = $entity->getTranslation($this->language()->getId()); + $attribute_values[$field_name] = $attribute_value; } } @@ -295,7 +299,9 @@ public function getAttributeValue($field_name) { $attribute_value = NULL; $field = $this->get($field_name); if (!$field->isEmpty()) { - $attribute_value = $field->entity; + /** @var \Drupal\commerce_product\Entity\ProductAttributeValueInterface $entity */ + $entity = $field->entity; + $attribute_value = $entity->getTranslation($this->language()->getId()); } return $attribute_value; diff --git a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php index 288364f10..9f36d809c 100644 --- a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php +++ b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php @@ -68,8 +68,8 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $items->getEntity()->id(), $this->viewMode, $this->getSetting('combine'), - ], - ], + $langcode, + ]], '#create_placeholder' => TRUE, ]; } diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php index 7407ad2d4..1b2489ff2 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php @@ -86,7 +86,7 @@ public static function create(ContainerInterface $container, array $configuratio public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $form_state->get('product'); - $variations = $this->variationStorage->loadEnabled($product); + $variations = $product->getVariations(); if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. $form_state->set('hide_form', TRUE); @@ -239,7 +239,7 @@ protected function getAttributeInfo(ProductVariationInterface $selected_variatio $field = $field_definitions[$field_name]; $attributes[$field_name] = [ 'field_name' => $field_name, - 'title' => $field->getLabel(), + 'title' => $this->t($field->getLabel()), 'required' => $field->isRequired(), 'element_type' => $attribute_type->getElementType(), ]; diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationWidgetBase.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationWidgetBase.php index 4c9fd84b0..1b8115c19 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationWidgetBase.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationWidgetBase.php @@ -103,6 +103,11 @@ public static function ajaxRefresh(array $form, FormStateInterface $form_state) $response = $ajax_renderer->renderResponse($form, $request, $route_match); $variation = ProductVariation::load($form_state->get('selected_variation')); + /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ + $product = $form_state->get('product'); + if ($variation->hasTranslation($product->language()->getId())) { + $variation = $variation->getTranslation($product->language()->getId()); + } /** @var \Drupal\commerce_product\ProductVariationFieldRendererInterface $variation_field_renderer */ $variation_field_renderer = \Drupal::service('commerce_product.variation_field_renderer'); $view_mode = $form_state->get('form_display')->getMode(); diff --git a/modules/product/src/ProductLazyBuilders.php b/modules/product/src/ProductLazyBuilders.php index 195f0cde3..0807bc282 100644 --- a/modules/product/src/ProductLazyBuilders.php +++ b/modules/product/src/ProductLazyBuilders.php @@ -46,15 +46,21 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Ent * The view mode used to render the product. * @param bool $combine * TRUE to combine order items containing the same product variation. + * @param string $langcode + * The langcode for the language that should be used in form. * * @return array * A renderable array containing the cart form. */ - public function addToCartForm($product_id, $view_mode, $combine) { + public function addToCartForm($product_id, $view_mode, $combine, $langcode) { /** @var \Drupal\commerce_order\OrderItemStorageInterface $order_item_storage */ $order_item_storage = $this->entityTypeManager->getStorage('commerce_order_item'); /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $this->entityTypeManager->getStorage('commerce_product')->load($product_id); + // Load Product for current language. + if ($product->isTranslatable() && $product->language()->getId() != $langcode && $product->hasTranslation($langcode)) { + $product = $product->getTranslation($langcode); + } $default_variation = $product->getDefaultVariation(); if (!$default_variation) { return []; diff --git a/src/Entity/CommerceContentEntityBase.php b/src/Entity/CommerceContentEntityBase.php new file mode 100644 index 000000000..441604cb9 --- /dev/null +++ b/src/Entity/CommerceContentEntityBase.php @@ -0,0 +1,48 @@ +get($field_name)->referencedEntities(); + return $this->ensureTranslations($refereced_entities); + } + + /** + * Ensures that the provided entities are in the current entity's language if + * entity is translatable or current interface language otherwise. + * + * @param \Drupal\Core\Entity\ContentEntityInterface[] $entities + * The entities to process. + * + * @return \Drupal\Core\Entity\ContentEntityInterface[] + * The processed entities. + */ + protected function ensureTranslations(array $entities) { + if ($this->isTranslatable()) { + $langcode = $this->language()->getId(); + } + else { + $langcode = $this->languageManager()->getCurrentLanguage(LanguageInterface::TYPE_INTERFACE)->getId(); + } + foreach ($entities as $index => $entity) { + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + if ($entity->hasTranslation($langcode)) { + $entities[$index] = $entity->getTranslation($langcode); + } + } + + return $entities; + } + +} diff --git a/src/Entity/CommerceContentEntityInterface.php b/src/Entity/CommerceContentEntityInterface.php new file mode 100644 index 000000000..61aecda7f --- /dev/null +++ b/src/Entity/CommerceContentEntityInterface.php @@ -0,0 +1,23 @@ + Date: Tue, 21 Mar 2017 10:35:15 +0000 Subject: [PATCH 02/24] Some updates for PR reviews. --- modules/order/src/Entity/Order.php | 7 ++++--- .../Field/FieldFormatter/AddToCartFormatter.php | 11 ++++++----- .../ProductVariationAttributesWidget.php | 21 +++++++++++++++++++-- modules/promotion/src/Entity/Promotion.php | 6 +++--- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/modules/order/src/Entity/Order.php b/modules/order/src/Entity/Order.php index 2e2682000..ca9472271 100644 --- a/modules/order/src/Entity/Order.php +++ b/modules/order/src/Entity/Order.php @@ -2,10 +2,10 @@ namespace Drupal\commerce_order\Entity; +use Drupal\commerce\Entity\CommerceContentEntityBase; use Drupal\commerce_order\Adjustment; use Drupal\commerce_price\Price; use Drupal\commerce_store\Entity\StoreInterface; -use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -66,7 +66,7 @@ * field_ui_base_route = "entity.commerce_order_type.edit_form" * ) */ -class Order extends ContentEntityBase implements OrderInterface { +class Order extends CommerceContentEntityBase implements OrderInterface { use EntityChangedTrait; @@ -89,7 +89,8 @@ public function setOrderNumber($order_number) { * {@inheritdoc} */ public function getStore() { - return $this->get('store_id')->entity; + $store = $this->getTranslatedReferencedEntities('store_id'); + return reset($store); } /** diff --git a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php index 9f36d809c..b32bedfad 100644 --- a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php +++ b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php @@ -65,11 +65,12 @@ public function settingsSummary() { public function viewElements(FieldItemListInterface $items, $langcode) { return [ '#lazy_builder' => ['commerce_product.lazy_builders:addToCartForm', [ - $items->getEntity()->id(), - $this->viewMode, - $this->getSetting('combine'), - $langcode, - ]], + $items->getEntity()->id(), + $this->viewMode, + $this->getSetting('combine'), + $langcode, + ], + ], '#create_placeholder' => TRUE, ]; } diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php index 1b2489ff2..7d83b5f3f 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php @@ -6,6 +6,7 @@ use Drupal\commerce_product\ProductAttributeFieldManagerInterface; use Drupal\Component\Utility\Html; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; @@ -27,6 +28,13 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implements ContainerFactoryPluginInterface { /** + * The entity repository service. + * + * @var \Drupal\Core\Entity\EntityRepositoryInterface + */ + protected $entityRepository; + + /** * The attribute field manager. * * @var \Drupal\commerce_product\ProductAttributeFieldManagerInterface @@ -58,9 +66,10 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem * @param \Drupal\commerce_product\ProductAttributeFieldManagerInterface $attribute_field_manager * The attribute field manager. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, ProductAttributeFieldManagerInterface $attribute_field_manager) { + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository, ProductAttributeFieldManagerInterface $attribute_field_manager) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $entity_type_manager); + $this->entityRepository = $entity_repository; $this->attributeFieldManager = $attribute_field_manager; $this->attributeStorage = $entity_type_manager->getStorage('commerce_product_attribute'); } @@ -76,6 +85,7 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['settings'], $configuration['third_party_settings'], $container->get('entity_type.manager'), + $container->get('entity.repository'), $container->get('commerce_product.attribute_field_manager') ); } @@ -86,6 +96,7 @@ public static function create(ContainerInterface $container, array $configuratio public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $form_state->get('product'); + $langcode = $product->language()->getId(); $variations = $product->getVariations(); if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. @@ -130,6 +141,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $selected_variation = reset($variations); } } + // Make sure we use the translated selected variation. + if ($selected_variation->hasTranslation($langcode)) { + $selected_variation = $selected_variation->getTranslation($langcode); + } $element['variation'] = [ '#type' => 'value', @@ -236,10 +251,12 @@ protected function getAttributeInfo(ProductVariationInterface $selected_variatio foreach ($field_names as $field_name) { /** @var \Drupal\commerce_product\Entity\ProductAttributeInterface $attribute_type */ $attribute_type = $this->attributeStorage->load(substr($field_name, 10)); + // Make sure we have translation for attribute. + $attribute_type = $this->entityRepository->getTranslationFromContext($attribute_type, $selected_variation->language()->getId()); $field = $field_definitions[$field_name]; $attributes[$field_name] = [ 'field_name' => $field_name, - 'title' => $this->t($field->getLabel()), + 'title' => $attribute_type->label(), 'required' => $field->isRequired(), 'element_type' => $attribute_type->getElementType(), ]; diff --git a/modules/promotion/src/Entity/Promotion.php b/modules/promotion/src/Entity/Promotion.php index 95932bba9..4501dc208 100644 --- a/modules/promotion/src/Entity/Promotion.php +++ b/modules/promotion/src/Entity/Promotion.php @@ -2,8 +2,8 @@ namespace Drupal\commerce_promotion\Entity; +use Drupal\commerce\Entity\CommerceContentEntityBase; use Drupal\Core\Datetime\DrupalDateTime; -use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -65,7 +65,7 @@ * }, * ) */ -class Promotion extends ContentEntityBase implements PromotionInterface { +class Promotion extends CommerceContentEntityBase implements PromotionInterface { /** * {@inheritdoc} @@ -135,7 +135,7 @@ public function setOrderTypeIds(array $order_type_ids) { * {@inheritdoc} */ public function getStores() { - return $this->get('stores')->referencedEntities(); + return $this->getTranslatedReferencedEntities('stores'); } /** From 405c3506d720ff0251d6c4b80832e8c52253228d Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Tue, 21 Mar 2017 11:47:20 +0000 Subject: [PATCH 03/24] Make sure we use translated variations for Product variation title widget. --- .../src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php index e6a95d672..0b050f38d 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php @@ -72,7 +72,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $form_state->get('product'); /** @var \Drupal\commerce_product\Entity\ProductVariationInterface[] $variations */ - $variations = $this->variationStorage->loadEnabled($product); + foreach ($product->getVariations() as $variation) { + $variations[$variation->id()] = $variation; + } if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. $form_state->set('hide_form', TRUE); @@ -152,8 +154,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen * The selected variation. */ protected function selectVariationFromUserInput(array $variations, array $user_input) { - $current_variation = NULL; - if (!empty($user_input['variation']) && $variations[$user_input['variation']]) { + $current_variation = reset($variations); + if (!empty($user_input) && !empty($user_input['variation']) && $variations[$user_input['variation']]) { $current_variation = $variations[$user_input['variation']]; } From 00af086f40119992c4b1ad0904665d72c274ce96 Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Tue, 21 Mar 2017 11:51:50 +0000 Subject: [PATCH 04/24] Some updates for travis errors - code standards. --- .../src/Plugin/Field/FieldFormatter/AddToCartFormatter.php | 10 +++++----- .../Field/FieldWidget/ProductVariationAttributesWidget.php | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php index b32bedfad..6f3eb0599 100644 --- a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php +++ b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php @@ -65,11 +65,11 @@ public function settingsSummary() { public function viewElements(FieldItemListInterface $items, $langcode) { return [ '#lazy_builder' => ['commerce_product.lazy_builders:addToCartForm', [ - $items->getEntity()->id(), - $this->viewMode, - $this->getSetting('combine'), - $langcode, - ], + $items->getEntity()->id(), + $this->viewMode, + $this->getSetting('combine'), + $langcode, + ], ], '#create_placeholder' => TRUE, ]; diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php index 7d83b5f3f..b24e47ebc 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php @@ -63,6 +63,8 @@ class ProductVariationAttributesWidget extends ProductVariationWidgetBase implem * Any third party settings. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. + * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository + * The entity repository. * @param \Drupal\commerce_product\ProductAttributeFieldManagerInterface $attribute_field_manager * The attribute field manager. */ From ddd266bf0ea59e6266f7bf7af5a427fdebeb2cf2 Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Tue, 21 Mar 2017 16:50:36 +0000 Subject: [PATCH 05/24] Add some tests. --- .../AddToCartMultilingualTest.php | 237 +++++++++++++++++++++ .../FieldWidget/ProductVariationTitleWidget.php | 3 +- 2 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php new file mode 100644 index 000000000..dfbf623f2 --- /dev/null +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -0,0 +1,237 @@ +save(); + + /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface $variation_type */ + $variation_type = ProductVariationType::load($this->variation->bundle()); + + $color_attributes = $this->createAttributeSet($variation_type, 'color', [ + 'red' => 'Red', + 'blue' => 'Blue', + ]); + $updated_color_attributes = []; + foreach ($color_attributes as $key => $color_attribute) { + $color_attribute_fr = $color_attribute->toArray(); + $color_attribute_fr['name'] = 'FR ' . $color_attribute->label(); + $color_attribute->addTranslation('fr', $color_attribute_fr)->save(); + $updated_color_attributes[$key] = $color_attribute; + } + $size_attributes = $this->createAttributeSet($variation_type, 'size', [ + 'small' => 'Small', + 'medium' => 'Medium', + 'large' => 'Large', + ]); + $updated_size_attributes = []; + foreach ($size_attributes as $key => $size_attribute) { + $size_attribute_fr = $size_attribute->toArray(); + $size_attribute_fr['name'] = 'FR ' . $size_attribute->label(); + $size_attribute->addTranslation('fr', $size_attribute_fr)->save(); + $updated_size_attributes[$key] = $size_attribute; + } + + // Reload the variation since we have new fields. + $this->variation = ProductVariation::load($this->variation->id()); + $product = $this->variation->getProduct(); + $product->setTitle('Title'); + $product->save(); + // Add translation + $product_fr = $product->toArray(); + $product_fr['title'] = 'FR title'; + $product->addTranslation('fr', $product_fr)->save(); + + // Update first variation to have the attribute's value. + $this->variation->attribute_color = $color_attributes['red']->id(); + $this->variation->attribute_size = $size_attributes['small']->id(); + $this->variation->save(); + + $variation_fr = $this->variation->toArray(); + $this->variation->addTranslation('fr', $variation_fr)->save(); + + // The matrix is intentionally uneven, blue / large is missing. + $attribute_values_matrix = [ + ['red', 'small'], + ['red', 'medium'], + ['red', 'large'], + ['blue', 'small'], + ['blue', 'medium'], + ]; + $variations = [ + $this->variation, + ]; + // Generate variations off of the attributes values matrix. + foreach ($attribute_values_matrix as $key => $value) { + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = $this->createEntity('commerce_product_variation', [ + 'type' => $variation_type->id(), + 'sku' => $this->randomMachineName(), + 'price' => [ + 'number' => 999, + 'currency_code' => 'USD', + ], + 'attribute_color' => $updated_color_attributes[$value[0]], + 'attribute_size' => $updated_size_attributes[$value[1]], + ]); + $variation->save(); + $variation_fr = $variation->toArray(); + $variation->addTranslation('fr', $variation_fr)->save(); + $variation = ProductVariation::load($variation->id()); + $variations[] = $variation; + $product->variations->appendItem($variation); + } + $product->save(); + $this->product = Product::load($product->id()); + + $this->variations = $variations; + $this->colorAttributes = $updated_color_attributes; + $this->sizeAttributes = $updated_size_attributes; + + } + + /** + * Tests adding a product to the cart using + * 'commerce_product_variation_attributes' widget. + */ + public function te2222stProductVariationAttributesWidget() { + $this->drupalGet($this->product->toUrl()); + $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_color]', 'Red'); + $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_size]', 'Small'); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_color]', $this->colorAttributes['blue']->id()); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_size]', $this->sizeAttributes['medium']->id()); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_size]', $this->sizeAttributes['large']->id()); + $this->getSession()->getPage()->pressButton('Add to cart'); + + // Change the site language. + $this->config('system.site')->set('default_langcode', 'fr')->save(); + $this->drupalGet($this->product->toUrl()); + // Use AJAX to change the size to Medium, keeping the color on Red. + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][attributes][attribute_size]', 'FR Medium'); + $this->waitForAjaxToFinish(); + $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_color]', 'FR Red'); + $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_size]', 'FR Medium'); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_color]', $this->colorAttributes['blue']->id()); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_size]', $this->sizeAttributes['small']->id()); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_size]', $this->sizeAttributes['large']->id()); + + // Use AJAX to change the color to Blue, keeping the size on Medium. + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][attributes][attribute_color]', 'FR Blue'); + $this->waitForAjaxToFinish(); + $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_color]', 'FR Blue'); + $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_size]', 'FR Medium'); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_color]', $this->colorAttributes['red']->id()); + $this->assertAttributeExists('purchased_entity[0][attributes][attribute_size]', $this->sizeAttributes['small']->id()); + $this->assertAttributeDoesNotExist('purchased_entity[0][attributes][attribute_size]', $this->sizeAttributes['large']->id()); + $this->getSession()->getPage()->pressButton('Add to cart'); + + $this->cart = Order::load($this->cart->id()); + $order_items = $this->cart->getItems(); + $this->assertOrderItemInOrder($this->variations[0]->getTranslation('fr'), $order_items[0]); + $this->assertOrderItemInOrder($this->variations[5]->getTranslation('fr'), $order_items[1]); + } + + /** + * Tests adding a product to the cart using 'commerce_product_variation_title' + * widget. + */ + public function testProductVariationTitleWidget() { + // @todo + $order_item_form_display = EntityFormDisplay::load('commerce_order_item.default.add_to_cart'); + $order_item_form_display->setComponent('purchased_entity', [ + 'type' => 'commerce_product_variation_title' + ]); + $order_item_form_display->save(); + + $this->drupalGet($this->product->toUrl()); + $this->assertSession()->selectExists('purchased_entity[0][variation]'); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - Red, Small'); + $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - Red, Medium'); + $this->getSession()->getPage()->pressButton('Add to cart'); + + // Change the site language. + $this->config('system.site')->set('default_langcode', 'fr')->save(); + $this->drupalGet($this->product->toUrl()); + // Use AJAX to change the size to Medium, keeping the color on Red. + $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - FR Red, FR Small'); + $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Red, FR Medium'); + $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Red, FR Large'); + $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Blue, FR Small'); + $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Blue, FR Medium'); + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Title - FR Red, FR Medium'); + $this->waitForAjaxToFinish(); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - FR Red, FR Medium'); + $this->assertSession()->pageTextContains('Title - FR Red, FR Medium'); + + // Use AJAX to change the color to Blue, keeping the size on Medium. + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Title - FR Blue, FR Medium'); + $this->waitForAjaxToFinish(); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Blue, FR Medium'); + $this->assertSession()->pageTextContains('Title - FR Blue, FR Medium'); + $this->getSession()->getPage()->pressButton('Add to cart'); + + $this->cart = Order::load($this->cart->id()); + $order_items = $this->cart->getItems(); + $this->assertOrderItemInOrder($this->variations[0]->getTranslation('fr'), $order_items[0]); + $this->assertOrderItemInOrder($this->variations[5]->getTranslation('fr'), $order_items[1]); + } + +} diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php index 0b050f38d..682fed720 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php @@ -72,8 +72,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $form_state->get('product'); /** @var \Drupal\commerce_product\Entity\ProductVariationInterface[] $variations */ + $variations = []; foreach ($product->getVariations() as $variation) { - $variations[$variation->id()] = $variation; + $variations[] = $variation; } if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. From 879e28ce0ffd83e2195f31bcc910ee1db5e7ffeb Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Sat, 25 Mar 2017 15:22:56 +0000 Subject: [PATCH 06/24] Travis error messages. --- .../cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index dfbf623f2..16dd218e1 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -95,7 +95,7 @@ public function setUp() { $product = $this->variation->getProduct(); $product->setTitle('Title'); $product->save(); - // Add translation + // Add translation. $product_fr = $product->toArray(); $product_fr['title'] = 'FR title'; $product->addTranslation('fr', $product_fr)->save(); @@ -197,7 +197,7 @@ public function testProductVariationTitleWidget() { // @todo $order_item_form_display = EntityFormDisplay::load('commerce_order_item.default.add_to_cart'); $order_item_form_display->setComponent('purchased_entity', [ - 'type' => 'commerce_product_variation_title' + 'type' => 'commerce_product_variation_title', ]); $order_item_form_display->save(); From 83cd03ea209dfe9363d0cea54dc90cd805f87486 Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Tue, 28 Mar 2017 09:57:38 +0000 Subject: [PATCH 07/24] Fix for tests. --- .../AddToCartMultilingualTest.php | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index 16dd218e1..379f34f92 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -53,6 +53,7 @@ class AddToCartMultilingualTest extends CartBrowserTestBase { */ public static $modules = [ 'language', + 'content_translation', ]; /** @@ -61,10 +62,16 @@ class AddToCartMultilingualTest extends CartBrowserTestBase { public function setUp() { parent::setUp(); // Add a new language. - ConfigurableLanguage::createFromLangcode('fr')->save(); + ConfigurableLanguage::createFRomLangcode('fr')->save(); /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface $variation_type */ $variation_type = ProductVariationType::load($this->variation->bundle()); + // Enable translation for the product and ensure the change is picked up. + \Drupal::service('content_translation.manager')->setEnabled('commerce_product_variation', $variation_type->id(), TRUE); + drupal_static_reset(); + \Drupal::entityManager()->clearCachedDefinitions(); + \Drupal::service('router.builder')->rebuild(); + \Drupal::service('entity.definition_update_manager')->applyUpdates(); $color_attributes = $this->createAttributeSet($variation_type, 'color', [ 'red' => 'Red', @@ -129,30 +136,32 @@ public function setUp() { 'number' => 999, 'currency_code' => 'USD', ], - 'attribute_color' => $updated_color_attributes[$value[0]], - 'attribute_size' => $updated_size_attributes[$value[1]], ]); + $variation->attribute_color = $updated_color_attributes[$value[0]]; + $variation->attribute_size = $updated_size_attributes[$value[1]]; $variation->save(); + $variation = ProductVariation::load($variation->id()); + $product->variations->appendItem($variation); + $product->save(); + // Add variation FR translation. $variation_fr = $variation->toArray(); $variation->addTranslation('fr', $variation_fr)->save(); - $variation = ProductVariation::load($variation->id()); + $variation->save(); $variations[] = $variation; - $product->variations->appendItem($variation); } $product->save(); $this->product = Product::load($product->id()); - $this->variations = $variations; + $this->variations = $product->getVariations(); $this->colorAttributes = $updated_color_attributes; $this->sizeAttributes = $updated_size_attributes; - } /** * Tests adding a product to the cart using * 'commerce_product_variation_attributes' widget. */ - public function te2222stProductVariationAttributesWidget() { + public function testProductVariationAttributesWidget() { $this->drupalGet($this->product->toUrl()); $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_color]', 'Red'); $this->assertAttributeSelected('purchased_entity[0][attributes][attribute_size]', 'Small'); @@ -194,7 +203,6 @@ public function te2222stProductVariationAttributesWidget() { * widget. */ public function testProductVariationTitleWidget() { - // @todo $order_item_form_display = EntityFormDisplay::load('commerce_order_item.default.add_to_cart'); $order_item_form_display->setComponent('purchased_entity', [ 'type' => 'commerce_product_variation_title', @@ -204,28 +212,23 @@ public function testProductVariationTitleWidget() { $this->drupalGet($this->product->toUrl()); $this->assertSession()->selectExists('purchased_entity[0][variation]'); $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - Red, Small'); - $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - Red, Medium'); $this->getSession()->getPage()->pressButton('Add to cart'); // Change the site language. $this->config('system.site')->set('default_langcode', 'fr')->save(); + $this->product = Product::load($this->product->id()); $this->drupalGet($this->product->toUrl()); // Use AJAX to change the size to Medium, keeping the color on Red. - $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - FR Red, FR Small'); - $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Red, FR Medium'); - $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Red, FR Large'); - $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Blue, FR Small'); - $this->assertAttributeExists('purchased_entity[0][variation]', 'Title - FR Blue, FR Medium'); - $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Title - FR Red, FR Medium'); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Red, FR Small'); + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'FR title - FR Red, FR Medium'); $this->waitForAjaxToFinish(); - $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - FR Red, FR Medium'); - $this->assertSession()->pageTextContains('Title - FR Red, FR Medium'); - + $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Red, FR Medium'); + $this->assertSession()->pageTextContains('FR title - FR Red, FR Medium'); // Use AJAX to change the color to Blue, keeping the size on Medium. - $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Title - FR Blue, FR Medium'); + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'FR title - FR Blue, FR Medium'); $this->waitForAjaxToFinish(); $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Blue, FR Medium'); - $this->assertSession()->pageTextContains('Title - FR Blue, FR Medium'); + $this->assertSession()->pageTextContains('FR title - FR Blue, FR Medium'); $this->getSession()->getPage()->pressButton('Add to cart'); $this->cart = Order::load($this->cart->id()); From 29c13a4b8ac1bde3dc39b61ea994bd1e7f7b9501 Mon Sep 17 00:00:00 2001 From: tavi toporjinschi Date: Tue, 25 Apr 2017 16:31:27 +0000 Subject: [PATCH 08/24] Fix for tests. --- modules/checkout/tests/src/Functional/CheckoutOrderTest.php | 8 ++++---- .../src/Plugin/Field/FieldFormatter/AddToCartFormatter.php | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/checkout/tests/src/Functional/CheckoutOrderTest.php b/modules/checkout/tests/src/Functional/CheckoutOrderTest.php index 7be712dae..59b8bf6c6 100644 --- a/modules/checkout/tests/src/Functional/CheckoutOrderTest.php +++ b/modules/checkout/tests/src/Functional/CheckoutOrderTest.php @@ -79,7 +79,7 @@ protected function setUp() { */ public function testGuestOrderCheckout() { $this->drupalLogout(); - $this->drupalGet($this->product->toUrl()->toString()); + $this->drupalGet($this->product->toUrl()); $this->submitForm([], 'Add to cart'); $this->assertSession()->pageTextContains('1 item'); $cart_link = $this->getSession()->getPage()->findLink('your cart'); @@ -105,7 +105,7 @@ public function testGuestOrderCheckout() { $this->assertSession()->pageTextContains('Your order number is 1. You can view your order on your account page when logged in.'); $this->assertSession()->pageTextContains('0 items'); // Test second order. - $this->drupalGet($this->product->toUrl()->toString()); + $this->drupalGet($this->product->toUrl()); $this->submitForm([], 'Add to cart'); $this->assertSession()->pageTextContains('1 item'); $cart_link = $this->getSession()->getPage()->findLink('your cart'); @@ -142,7 +142,7 @@ public function testRegisterOrderCheckout() { $config->save(); $this->drupalLogout(); - $this->drupalGet($this->product->toUrl()->toString()); + $this->drupalGet($this->product->toUrl()); $this->submitForm([], 'Add to cart'); $cart_link = $this->getSession()->getPage()->findLink('your cart'); $cart_link->click(); @@ -255,7 +255,7 @@ public function testCheckoutFlowOnCartUpdate() { 'stores' => [$this->store], ]); // Adding a new product to the cart resets the checkout step. - $this->drupalGet($product2->toUrl()->toString()); + $this->drupalGet($product2->toUrl()); $this->submitForm([], 'Add to cart'); $this->getSession()->getPage()->findLink('your cart')->click(); $this->submitForm([], 'Checkout'); diff --git a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php index 8c8fee6f8..deb71c0fb 100644 --- a/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php +++ b/modules/product/src/Plugin/Field/FieldFormatter/AddToCartFormatter.php @@ -70,6 +70,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $items->getEntity()->id(), $this->viewMode, $this->getSetting('combine'), + $langcode, ], ], '#create_placeholder' => TRUE, From 6be831384ca1a7e4fd3c10e96af93a6de8bc8579 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Wed, 11 Oct 2017 12:39:45 -0500 Subject: [PATCH 09/24] Fix VariationStoreage::loadEnabled --- modules/product/src/ProductVariationStorage.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/product/src/ProductVariationStorage.php b/modules/product/src/ProductVariationStorage.php index 538b5b23c..5b4861e4c 100644 --- a/modules/product/src/ProductVariationStorage.php +++ b/modules/product/src/ProductVariationStorage.php @@ -115,6 +115,19 @@ public function loadEnabled(ProductInterface $product) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $enabled_variation */ $enabled_variations = $this->loadMultiple($result); + + if ($product->isTranslatable()) { + $langcode = $product->language()->getId(); + foreach ($enabled_variations as $index => $enabled_variation) { + if (!$enabled_variation->hasTranslation($langcode)) { + unset($enabled_variations[$index]); + } + else { + $enabled_variations[$index] = $enabled_variation->getTranslation($langcode); + } + } + } + // Allow modules to apply own filtering (based on date, stock, etc). $event = new FilterVariationsEvent($product, $enabled_variations); $this->eventDispatcher->dispatch(ProductEvents::FILTER_VARIATIONS, $event); From 1730dba9f6bad1ab3a1bab479686c2e3f5a1d56e Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Wed, 11 Oct 2017 13:22:06 -0500 Subject: [PATCH 10/24] Use loadEnabled --- .../Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php index c8f91f547..5c2cc3464 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationAttributesWidget.php @@ -98,8 +98,7 @@ public static function create(ContainerInterface $container, array $configuratio public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $form_state->get('product'); - $langcode = $product->language()->getId(); - $variations = $product->getVariations(); + $variations = $this->variationStorage->loadEnabled($product); if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. $form_state->set('hide_form', TRUE); @@ -155,11 +154,6 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen } } - // Make sure we use the translated selected variation. - if ($selected_variation->hasTranslation($langcode)) { - $selected_variation = $selected_variation->getTranslation($langcode); - } - $element['variation'] = [ '#type' => 'value', '#value' => $selected_variation->id(), From 53279610e3d893fbc10da1d73f9ed9fa082dddb8 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Wed, 18 Oct 2017 11:29:51 -0500 Subject: [PATCH 11/24] Use entity repository --- modules/product/commerce_product.services.yml | 2 +- modules/product/src/Entity/Product.php | 2 +- modules/product/src/Entity/ProductVariation.php | 3 +-- modules/product/src/ProductLazyBuilders.php | 18 +++++++++++---- modules/product/src/ProductVariationStorage.php | 30 ++++++++++++++++--------- src/Entity/CommerceContentEntityBase.php | 12 ++++++++-- src/Entity/CommerceContentEntityInterface.php | 13 ++++++++++- 7 files changed, 58 insertions(+), 22 deletions(-) diff --git a/modules/product/commerce_product.services.yml b/modules/product/commerce_product.services.yml index cca824dbe..b86b802e7 100644 --- a/modules/product/commerce_product.services.yml +++ b/modules/product/commerce_product.services.yml @@ -5,7 +5,7 @@ services: commerce_product.lazy_builders: class: Drupal\commerce_product\ProductLazyBuilders - arguments: ['@entity_type.manager', '@form_builder'] + arguments: ['@entity_type.manager', '@form_builder', '@entity.repository'] commerce_product.variation_field_renderer: class: Drupal\commerce_product\ProductVariationFieldRenderer diff --git a/modules/product/src/Entity/Product.php b/modules/product/src/Entity/Product.php index f2469355f..439a9663a 100644 --- a/modules/product/src/Entity/Product.php +++ b/modules/product/src/Entity/Product.php @@ -251,7 +251,7 @@ public function getDefaultVariation() { foreach ($this->getVariations() as $variation) { // Return the first active variation. if ($variation->isActive() && $variation->access('view')) { - return $variation; + return $variation->getTranslation($this->language()->getId()); } } } diff --git a/modules/product/src/Entity/ProductVariation.php b/modules/product/src/Entity/ProductVariation.php index 2a1696a37..d4e5be0d8 100644 --- a/modules/product/src/Entity/ProductVariation.php +++ b/modules/product/src/Entity/ProductVariation.php @@ -91,8 +91,7 @@ public function toUrl($rel = 'canonical', array $options = []) { * {@inheritdoc} */ public function getProduct() { - $product = $this->getTranslatedReferencedEntities('product_id'); - return reset($product); + return $this->getTranslatedReferencedEntity('product_id'); } /** diff --git a/modules/product/src/ProductLazyBuilders.php b/modules/product/src/ProductLazyBuilders.php index 0299d4354..92db20ef3 100644 --- a/modules/product/src/ProductLazyBuilders.php +++ b/modules/product/src/ProductLazyBuilders.php @@ -2,6 +2,7 @@ namespace Drupal\commerce_product; +use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormState; @@ -26,16 +27,26 @@ class ProductLazyBuilders { protected $formBuilder; /** + * The entity repository. + * + * @var \Drupal\Core\Entity\EntityRepositoryInterface + */ + protected $entityRepository; + + /** * Constructs a new CartLazyBuilders object. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\Core\Form\FormBuilderInterface $form_builder * The form builder. + * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository + * The entity repository. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder, EntityRepositoryInterface $entity_repository) { $this->entityTypeManager = $entity_type_manager; $this->formBuilder = $form_builder; + $this->entityRepository = $entity_repository; } /** @@ -59,9 +70,8 @@ public function addToCartForm($product_id, $view_mode, $combine, $langcode) { /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $this->entityTypeManager->getStorage('commerce_product')->load($product_id); // Load Product for current language. - if ($product->isTranslatable() && $product->language()->getId() != $langcode && $product->hasTranslation($langcode)) { - $product = $product->getTranslation($langcode); - } + $product = $this->entityRepository->getTranslationFromContext($product, $langcode); + $default_variation = $product->getDefaultVariation(); if (!$default_variation) { return []; diff --git a/modules/product/src/ProductVariationStorage.php b/modules/product/src/ProductVariationStorage.php index 5b4861e4c..cf5d12aff 100644 --- a/modules/product/src/ProductVariationStorage.php +++ b/modules/product/src/ProductVariationStorage.php @@ -9,6 +9,7 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Language\LanguageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -28,6 +29,13 @@ class ProductVariationStorage extends CommerceContentEntityStorage implements Pr protected $requestStack; /** + * The entity repository. + * + * @var \Drupal\Core\Entity\EntityRepositoryInterface + */ + protected $entityRepository; + + /** * Constructs a new ProductVariationStorage object. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type @@ -44,11 +52,14 @@ class ProductVariationStorage extends CommerceContentEntityStorage implements Pr * The event dispatcher. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack * The request stack. + * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository + * The entity repository. */ - public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack) { + public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, EntityRepositoryInterface $entity_repository) { parent::__construct($entity_type, $database, $entity_manager, $cache, $language_manager, $event_dispatcher); $this->requestStack = $request_stack; + $this->entityRepository = $entity_repository; } /** @@ -62,7 +73,8 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $container->get('cache.entity'), $container->get('language_manager'), $container->get('event_dispatcher'), - $container->get('request_stack') + $container->get('request_stack'), + $container->get('entity.repository') ); } @@ -81,12 +93,13 @@ public function loadBySku($sku) { */ public function loadFromContext(ProductInterface $product) { $current_request = $this->requestStack->getCurrentRequest(); + $langcode = $product->language()->getId(); if ($variation_id = $current_request->query->get('v')) { if (in_array($variation_id, $product->getVariationIds())) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ $variation = $this->load($variation_id); if ($variation->isActive() && $variation->access('view')) { - return $variation; + return $this->entityRepository->getTranslationFromContext($variation, $langcode); } } } @@ -98,8 +111,8 @@ public function loadFromContext(ProductInterface $product) { */ public function loadEnabled(ProductInterface $product) { $ids = []; - foreach ($product->variations as $variation) { - $ids[$variation->target_id] = $variation->target_id; + foreach ($product->getVariationIds() as $variation_id) { + $ids[$variation_id] = $variation_id; } // Speed up loading by filtering out the IDs of disabled variations. $query = $this->getQuery() @@ -119,12 +132,7 @@ public function loadEnabled(ProductInterface $product) { if ($product->isTranslatable()) { $langcode = $product->language()->getId(); foreach ($enabled_variations as $index => $enabled_variation) { - if (!$enabled_variation->hasTranslation($langcode)) { - unset($enabled_variations[$index]); - } - else { - $enabled_variations[$index] = $enabled_variation->getTranslation($langcode); - } + $enabled_variations[$index] = $this->entityRepository->getTranslationFromContext($enabled_variation, $langcode); } } diff --git a/src/Entity/CommerceContentEntityBase.php b/src/Entity/CommerceContentEntityBase.php index 441604cb9..7d448934f 100644 --- a/src/Entity/CommerceContentEntityBase.php +++ b/src/Entity/CommerceContentEntityBase.php @@ -14,8 +14,16 @@ class CommerceContentEntityBase extends ContentEntityBase implements CommerceCon * {@inheritdoc} */ public function getTranslatedReferencedEntities($field_name) { - $refereced_entities = $this->get($field_name)->referencedEntities(); - return $this->ensureTranslations($refereced_entities); + $referenced_entities = $this->get($field_name)->referencedEntities(); + return $this->ensureTranslations($referenced_entities); + } + + /** + * {@inheritdoc} + */ + public function getTranslatedReferencedEntity($field_name) { + $referenced_entities = $this->getTranslatedReferencedEntities($field_name); + return reset($referenced_entities); } /** diff --git a/src/Entity/CommerceContentEntityInterface.php b/src/Entity/CommerceContentEntityInterface.php index 61aecda7f..cb8964c53 100644 --- a/src/Entity/CommerceContentEntityInterface.php +++ b/src/Entity/CommerceContentEntityInterface.php @@ -16,8 +16,19 @@ * The entity reference field name. * * @return \Drupal\Core\Entity\ContentEntityInterface[] - * The entities.array + * The entities. */ public function getTranslatedReferencedEntities($field_name); + /** + * Gets the translation of an referenced entity. + * + * @param $field_name + * The entity reference field name. + * + * @return \Drupal\Core\Entity\ContentEntityInterface + * The entity. + */ + public function getTranslatedReferencedEntity($field_name); + } From 71768ab235af9632cd856dd46065da3f3d8cc94e Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Wed, 18 Oct 2017 13:08:16 -0500 Subject: [PATCH 12/24] Add more explicit testing. --- .../AddToCartMultilingualTest.php | 13 +- modules/product/src/ProductVariationStorage.php | 2 +- .../ProductVariationStorageMultilingualTest.php | 145 +++++++++++++++++++++ .../src/Kernel/ProductVariationStorageTest.php | 35 +++++ src/Entity/CommerceContentEntityBase.php | 3 +- src/Entity/CommerceContentEntityInterface.php | 2 +- 6 files changed, 192 insertions(+), 8 deletions(-) create mode 100644 modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index 379f34f92..aa4022779 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -2,13 +2,13 @@ namespace Drupal\Tests\commerce_cart\FunctionalJavascript; +use Drupal\commerce_order\Entity\Order; use Drupal\commerce_product\Entity\Product; +use Drupal\commerce_product\Entity\ProductVariation; +use Drupal\commerce_product\Entity\ProductVariationType; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\commerce\FunctionalJavascript\JavascriptTestTrait; -use Drupal\commerce_order\Entity\Order; -use Drupal\commerce_product\Entity\ProductVariation; -use Drupal\commerce_product\Entity\ProductVariationType; use Drupal\Tests\commerce_cart\Functional\CartBrowserTestBase; /** @@ -62,16 +62,20 @@ class AddToCartMultilingualTest extends CartBrowserTestBase { public function setUp() { parent::setUp(); // Add a new language. - ConfigurableLanguage::createFRomLangcode('fr')->save(); + ConfigurableLanguage::createFromLangcode('fr')->save(); /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface $variation_type */ $variation_type = ProductVariationType::load($this->variation->bundle()); // Enable translation for the product and ensure the change is picked up. + // @see \Drupal\Tests\content_translation\Functional\ContentTranslationTestBase \Drupal::service('content_translation.manager')->setEnabled('commerce_product_variation', $variation_type->id(), TRUE); drupal_static_reset(); \Drupal::entityManager()->clearCachedDefinitions(); \Drupal::service('router.builder')->rebuild(); \Drupal::service('entity.definition_update_manager')->applyUpdates(); + // Rebuild the container so that the new languages are picked up by services + // that hold a list of languages. + $this->rebuildContainer(); $color_attributes = $this->createAttributeSet($variation_type, 'color', [ 'red' => 'Red', @@ -172,6 +176,7 @@ public function testProductVariationAttributesWidget() { // Change the site language. $this->config('system.site')->set('default_langcode', 'fr')->save(); + $this->drupalGet($this->product->toUrl()); // Use AJAX to change the size to Medium, keeping the color on Red. $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][attributes][attribute_size]', 'FR Medium'); diff --git a/modules/product/src/ProductVariationStorage.php b/modules/product/src/ProductVariationStorage.php index cf5d12aff..fc830b2fa 100644 --- a/modules/product/src/ProductVariationStorage.php +++ b/modules/product/src/ProductVariationStorage.php @@ -85,7 +85,7 @@ public function loadBySku($sku) { $variations = $this->loadByProperties(['sku' => $sku]); $variation = reset($variations); - return $variation ?: NULL; + return $variation ? $this->entityRepository->getTranslationFromContext($variation) : NULL; } /** diff --git a/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php b/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php new file mode 100644 index 000000000..e723ce78d --- /dev/null +++ b/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php @@ -0,0 +1,145 @@ +installEntitySchema('commerce_product_variation'); + $this->installEntitySchema('commerce_product'); + $this->installConfig(['commerce_product']); + + $this->variationStorage = $this->container->get('entity_type.manager')->getStorage('commerce_product_variation'); + $this->languageManager = $this->container->get('language_manager'); + $this->languageDefault = $this->container->get('language.default'); + + ConfigurableLanguage::createFromLangcode('fr')->save(); + ConfigurableLanguage::createFromLangcode('sr')->save(); + ConfigurableLanguage::createFromLangcode('de')->save(); + + $variation_type = ProductVariationType::load('default'); + $this->container->get('content_translation.manager') + ->setEnabled('commerce_product_variation', $variation_type->id(), TRUE); + + $sku = 'STORAGE-MULTILINGUAL-TEST'; + $variation = ProductVariation::create([ + 'type' => 'default', + 'sku' => $sku, + 'title' => 'English variation', + ]); + $variation->addTranslation('fr', [ + 'title' => 'Variation française', + ]); + $variation->addTranslation('sr', [ + 'title' => 'Srpska varijacija', + ]); + $variation->save(); + $product = Product::create([ + 'type' => 'default', + 'variations' => [$variation], + ]); + $product->addTranslation('fr'); + $product->addTranslation('sr'); + $product->save(); + } + + /** + * Tests loading variations by SKU in French. + */ + public function testLoadBySkuFr() { + $this->languageDefault->set($this->languageManager->getLanguage('fr')); + $result = $this->variationStorage->loadBySku($this->testSku); + $this->assertEquals('Variation française', $result->label()); + } + + /** + * Tests loading variations by SKU in Serbian. + */ + public function testLoadBySkuSr() { + $this->languageDefault->set($this->languageManager->getLanguage('sr')); + $result = $this->variationStorage->loadBySku($this->testSku); + $this->assertEquals('Srpska varijacija', $result->label()); + } + + /** + * Tests loading variations by SKU in German (untranslated language.) + */ + public function testLoadBySkuDe() { + $this->languageDefault->set($this->languageManager->getLanguage('de')); + $result = $this->variationStorage->loadBySku($this->testSku); + // @todo how can we get this to fall back to `und`? + $this->assertEquals(NULL, $result->label()); + } + + /** + * Tests loadEnabled() method. + */ + public function testLoadEnabled() { + // @todo PORT AS MULTILINGUAL + } + + /** + * Tests loadFromContext() method. + */ + public function testLoadFromContext() { + // @todo PORT AS MULTILINGUAL + } + +} diff --git a/modules/product/tests/src/Kernel/ProductVariationStorageTest.php b/modules/product/tests/src/Kernel/ProductVariationStorageTest.php index d81176419..8a6ac6185 100644 --- a/modules/product/tests/src/Kernel/ProductVariationStorageTest.php +++ b/modules/product/tests/src/Kernel/ProductVariationStorageTest.php @@ -5,6 +5,7 @@ use Drupal\commerce_product\Entity\Product; use Drupal\commerce_product\Entity\ProductVariation; use Drupal\Tests\commerce\Kernel\CommerceKernelTestBase; +use Symfony\Component\HttpFoundation\Request; /** * Tests the product variation storage. @@ -94,4 +95,38 @@ public function testLoadEnabled() { $this->assertEquals(reset($variations)->getSku(), reset($variationsFiltered)->getSku(), 'The sort order of the variations remains the same'); } + /** + * Tests loadFromContext() method. + */ + public function testLoadFromContext() { + $variations = []; + for ($i = 1; $i <= 3; $i++) { + $variation = ProductVariation::create([ + 'type' => 'default', + 'sku' => strtolower($this->randomMachineName()), + 'title' => $this->randomString(), + ]); + $variation->save(); + $variations[] = $variation; + } + $variations = array_reverse($variations); + $product = Product::create([ + 'type' => 'default', + 'variations' => $variations, + ]); + $product->save(); + + $request = Request::create(''); + $request->query->add([ + 'v' => end($variations)->id(), + ]); + // Push the request to the request stack so `current_route_match` works. + $this->container->get('request_stack')->push($request); + + $this->assertNotEquals($request->query->get('v'), $product->getDefaultVariation()->id()); + + $context_variation = $this->variationStorage->loadFromContext($product); + $this->assertEquals($request->query->get('v'), $context_variation->id()); + } + } diff --git a/src/Entity/CommerceContentEntityBase.php b/src/Entity/CommerceContentEntityBase.php index 7d448934f..85774a18f 100644 --- a/src/Entity/CommerceContentEntityBase.php +++ b/src/Entity/CommerceContentEntityBase.php @@ -27,8 +27,7 @@ public function getTranslatedReferencedEntity($field_name) { } /** - * Ensures that the provided entities are in the current entity's language if - * entity is translatable or current interface language otherwise. + * Ensures entities are in the current entity's language, if possible. * * @param \Drupal\Core\Entity\ContentEntityInterface[] $entities * The entities to process. diff --git a/src/Entity/CommerceContentEntityInterface.php b/src/Entity/CommerceContentEntityInterface.php index cb8964c53..d776d1109 100644 --- a/src/Entity/CommerceContentEntityInterface.php +++ b/src/Entity/CommerceContentEntityInterface.php @@ -23,7 +23,7 @@ public function getTranslatedReferencedEntities($field_name); /** * Gets the translation of an referenced entity. * - * @param $field_name + * @param string $field_name * The entity reference field name. * * @return \Drupal\Core\Entity\ContentEntityInterface From f7a2183624f2c8f2b9866af11d22ed7891c2d3d5 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Wed, 18 Oct 2017 13:13:29 -0500 Subject: [PATCH 13/24] Ensure titles are translate if generated. --- modules/product/src/Entity/ProductVariation.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/modules/product/src/Entity/ProductVariation.php b/modules/product/src/Entity/ProductVariation.php index d4e5be0d8..822a2e548 100644 --- a/modules/product/src/Entity/ProductVariation.php +++ b/modules/product/src/Entity/ProductVariation.php @@ -371,6 +371,22 @@ protected function generateTitle() { return $title; } + public function addTranslation($langcode, array $values = []) { + $translation = parent::addTranslation($langcode, $values); + /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface $variation_type */ + $variation_type = $this->entityTypeManager() + ->getStorage('commerce_product_variation_type') + ->load($translation->bundle()); + + if ($variation_type->shouldGenerateTitle()) { + $title = $this->generateTitle(); + $translation->setTitle($title); + } + + return $translation; + } + + /** * {@inheritdoc} */ From dbcf16bc5688e67dd5fca41afa17da4ec31d856f Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 08:49:55 -0500 Subject: [PATCH 14/24] Fix kernel test --- modules/product/src/Entity/ProductVariation.php | 1 - .../ProductVariationStorageMultilingualTest.php | 55 +++++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/modules/product/src/Entity/ProductVariation.php b/modules/product/src/Entity/ProductVariation.php index 822a2e548..c73ba01fd 100644 --- a/modules/product/src/Entity/ProductVariation.php +++ b/modules/product/src/Entity/ProductVariation.php @@ -386,7 +386,6 @@ public function addTranslation($langcode, array $values = []) { return $translation; } - /** * {@inheritdoc} */ diff --git a/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php b/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php index e723ce78d..cb488fe18 100644 --- a/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php +++ b/modules/product/tests/src/Kernel/ProductVariationStorageMultilingualTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\commerce_product\Kernel; use Drupal\commerce_product\Entity\Product; +use Drupal\commerce_product\Entity\ProductType; use Drupal\commerce_product\Entity\ProductVariation; use Drupal\commerce_product\Entity\ProductVariationType; use Drupal\language\Entity\ConfigurableLanguage; @@ -45,6 +46,13 @@ class ProductVariationStorageMultilingualTest extends CommerceKernelTestBase { protected $testSku = 'STORAGE-MULTILINGUAL-TEST'; /** + * The test product. + * + * @var \Drupal\commerce_product\Entity\ProductInterface + */ + protected $product; + + /** * Modules to enable. * * @var array @@ -74,16 +82,35 @@ protected function setUp() { ConfigurableLanguage::createFromLangcode('sr')->save(); ConfigurableLanguage::createFromLangcode('de')->save(); - $variation_type = ProductVariationType::load('default'); + $variation_type = ProductVariationType::create([ + 'id' => 'multilingual', + 'label' => 'Multilingual', + 'orderItemType' => 'default', + 'generateTitle' => FALSE, + ]); + $variation_type->save(); $this->container->get('content_translation.manager') ->setEnabled('commerce_product_variation', $variation_type->id(), TRUE); + $product_type = ProductType::create([ + 'id' => 'multilingual', + 'label' => 'Multilingual', + 'variationType' => $variation_type->id(), + ]); + $product_type->save(); + commerce_product_add_stores_field($product_type); + commerce_product_add_variations_field($product_type); + $this->container->get('content_translation.manager') + ->setEnabled('commerce_product', $product_type->id(), TRUE); $sku = 'STORAGE-MULTILINGUAL-TEST'; $variation = ProductVariation::create([ - 'type' => 'default', + 'type' => $variation_type->id(), 'sku' => $sku, 'title' => 'English variation', ]); + $variation->save(); + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = $this->reloadEntity($variation); $variation->addTranslation('fr', [ 'title' => 'Variation française', ]); @@ -92,12 +119,13 @@ protected function setUp() { ]); $variation->save(); $product = Product::create([ - 'type' => 'default', + 'type' => $product_type->id(), 'variations' => [$variation], ]); $product->addTranslation('fr'); $product->addTranslation('sr'); $product->save(); + $this->product = $product; } /** @@ -124,22 +152,35 @@ public function testLoadBySkuSr() { public function testLoadBySkuDe() { $this->languageDefault->set($this->languageManager->getLanguage('de')); $result = $this->variationStorage->loadBySku($this->testSku); - // @todo how can we get this to fall back to `und`? - $this->assertEquals(NULL, $result->label()); + $this->assertEquals('English variation', $result->label()); } /** * Tests loadEnabled() method. */ public function testLoadEnabled() { - // @todo PORT AS MULTILINGUAL + $enabled = $this->variationStorage->loadEnabled($this->product); + $enabled_variation = reset($enabled); + $this->assertEquals($enabled_variation->language()->getId(), 'en'); + + $enabled = $this->variationStorage->loadEnabled($this->product->getTranslation('fr')); + $enabled_variation = reset($enabled); + $this->assertEquals($enabled_variation->language()->getId(), 'fr'); } /** * Tests loadFromContext() method. */ public function testLoadFromContext() { - // @todo PORT AS MULTILINGUAL + $product = $this->product->getTranslation('sr'); + $request = Request::create(''); + $request->query->add([ + 'v' => $product->getDefaultVariation()->id(), + ]); + // Push the request to the request stack so `current_route_match` works. + $this->container->get('request_stack')->push($request); + $context_variation = $this->variationStorage->loadFromContext($product); + $this->assertEquals($context_variation->language()->getId(), 'sr'); } } From 6e700d53767ddebef8298870f791791e74b64401 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 10:24:04 -0500 Subject: [PATCH 15/24] Test title generation, multilingual --- modules/product/src/Entity/ProductVariation.php | 16 -- .../Kernel/ProductVariationGeneratedTitleTest.php | 194 +++++++++++++++++++++ 2 files changed, 194 insertions(+), 16 deletions(-) create mode 100644 modules/product/tests/src/Kernel/ProductVariationGeneratedTitleTest.php diff --git a/modules/product/src/Entity/ProductVariation.php b/modules/product/src/Entity/ProductVariation.php index c73ba01fd..78d943d45 100644 --- a/modules/product/src/Entity/ProductVariation.php +++ b/modules/product/src/Entity/ProductVariation.php @@ -367,25 +367,9 @@ protected function generateTitle() { // When there are no attribute fields, there's only one variation. $title = $product_title; } - return $title; } - public function addTranslation($langcode, array $values = []) { - $translation = parent::addTranslation($langcode, $values); - /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface $variation_type */ - $variation_type = $this->entityTypeManager() - ->getStorage('commerce_product_variation_type') - ->load($translation->bundle()); - - if ($variation_type->shouldGenerateTitle()) { - $title = $this->generateTitle(); - $translation->setTitle($title); - } - - return $translation; - } - /** * {@inheritdoc} */ diff --git a/modules/product/tests/src/Kernel/ProductVariationGeneratedTitleTest.php b/modules/product/tests/src/Kernel/ProductVariationGeneratedTitleTest.php new file mode 100644 index 000000000..ecc6f3e75 --- /dev/null +++ b/modules/product/tests/src/Kernel/ProductVariationGeneratedTitleTest.php @@ -0,0 +1,194 @@ +installEntitySchema('commerce_product_variation'); + $this->installEntitySchema('commerce_product'); + $this->installEntitySchema('commerce_product_attribute'); + $this->installEntitySchema('commerce_product_attribute_value'); + $this->installConfig(['commerce_product']); + + ConfigurableLanguage::createFromLangcode('fr')->save(); + + $variation_type = ProductVariationType::create([ + 'id' => 'generate_title', + 'label' => 'Generate title test', + 'orderItemType' => 'default', + 'generateTitle' => TRUE, + ]); + $variation_type->save(); + $this->variationType = $variation_type; + + $product_type = ProductType::create([ + 'id' => 'generate_title', + 'label' => 'Generate title test', + 'variationType' => $variation_type->id(), + ]); + $product_type->save(); + commerce_product_add_stores_field($product_type); + commerce_product_add_variations_field($product_type); + $this->productType = $product_type; + + $color_attribute = ProductAttribute::create([ + 'id' => 'color', + 'label' => 'Color', + ]); + $color_attribute->save(); + $this->container + ->get('commerce_product.attribute_field_manager') + ->createField($color_attribute, $this->variationType->id()); + $this->attribute = $color_attribute; + } + + /** + * Tests the title is generated. + */ + public function testTitleGenerated() { + // Variations without a product have no title, because it can not be + // determined. + $variation = ProductVariation::create([ + 'type' => $this->variationType->id(), + ]); + $variation->save(); + $this->assertNull($variation->label()); + + // When variations have a product, but no attributes, the variation label + // should be the product's. + $product = Product::create([ + 'type' => $this->productType->id(), + 'title' => 'My Super Product', + 'variations' => [$variation], + ]); + $product->save(); + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = $this->reloadEntity($variation); + $this->assertEquals($variation->label(), $product->label()); + + // With attribute values, the variation title should be the product plus all + // of its attributes. + $color_black = ProductAttributeValue::create([ + 'attribute' => $this->attribute->id(), + 'name' => 'Black', + 'weight' => 3, + ]); + $color_black->save(); + + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = $this->reloadEntity($variation); + $variation->get('attribute_color')->setValue($color_black); + $variation->save(); + + $this->assertNotEquals($variation->label(), $product->label()); + $this->assertEquals($variation->label(), sprintf('%s - %s', $product->label(), $color_black->label())); + } + + /** + * Tests that creating a new variation creates a translated title. + */ + public function testMultilingualTitle() { + $this->container->get('content_translation.manager') + ->setEnabled('commerce_product_variation', $this->variationType->id(), TRUE); + $this->container->get('content_translation.manager') + ->setEnabled('commerce_product', $this->productType->id(), TRUE); + $this->container->get('content_translation.manager') + ->setEnabled('commerce_product_attribute_value', $this->attribute->id(), TRUE); + + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = ProductVariation::create([ + 'type' => $this->variationType->id(), + ]); + $variation->save(); + $this->assertNull($variation->label()); + $product = Product::create([ + 'type' => $this->productType->id(), + 'title' => 'My Super Product', + 'variations' => [$variation], + ]); + $product->addTranslation('fr', [ + 'title' => 'Mon super produit', + ]); + $product->save(); + + // Generating a translation of the variation should create a title which + // has the product's translated title. + $translation = $variation->addTranslation('fr', []); + $translation->save(); + + $this->assertEquals($product->getTranslation('fr')->label(), $variation->getTranslation('fr')->label()); + + // Verify translated attributes are used in the generated title. + $color_black = ProductAttributeValue::create([ + 'attribute' => $this->attribute->id(), + 'name' => 'Black', + 'weight' => 3, + ]); + $color_black->save(); + $color_black->addTranslation('fr', [ + 'name' => 'Noir', + ]); + $color_black->save(); + + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = $this->reloadEntity($variation); + $variation->get('attribute_color')->setValue($color_black); + $variation->save(); + $variation->getTranslation('fr')->save(); + $this->assertEquals($variation->getTranslation('fr')->label(), sprintf('%s - %s', $product->getTranslation('fr')->label(), $color_black->getTranslation('fr')->label())); + } + +} From 98983e6f9d26cbb9cb4c4d390948af7cc969af33 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 10:52:48 -0500 Subject: [PATCH 16/24] Work to fix functional JS test --- .../AddToCartMultilingualTest.php | 119 ++++++++++----------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index aa4022779..3b1373576 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -58,66 +58,55 @@ class AddToCartMultilingualTest extends CartBrowserTestBase { /** * {@inheritdoc} + * + * @see \Drupal\Tests\content_translation\Functional\ContentTranslationTestBase */ public function setUp() { parent::setUp(); - // Add a new language. - ConfigurableLanguage::createFromLangcode('fr')->save(); + + $this->setupMultilingual(); /** @var \Drupal\commerce_product\Entity\ProductVariationTypeInterface $variation_type */ $variation_type = ProductVariationType::load($this->variation->bundle()); - // Enable translation for the product and ensure the change is picked up. - // @see \Drupal\Tests\content_translation\Functional\ContentTranslationTestBase - \Drupal::service('content_translation.manager')->setEnabled('commerce_product_variation', $variation_type->id(), TRUE); - drupal_static_reset(); - \Drupal::entityManager()->clearCachedDefinitions(); - \Drupal::service('router.builder')->rebuild(); - \Drupal::service('entity.definition_update_manager')->applyUpdates(); - // Rebuild the container so that the new languages are picked up by services - // that hold a list of languages. - $this->rebuildContainer(); - $color_attributes = $this->createAttributeSet($variation_type, 'color', [ 'red' => 'Red', 'blue' => 'Blue', ]); - $updated_color_attributes = []; + foreach ($color_attributes as $key => $color_attribute) { - $color_attribute_fr = $color_attribute->toArray(); - $color_attribute_fr['name'] = 'FR ' . $color_attribute->label(); - $color_attribute->addTranslation('fr', $color_attribute_fr)->save(); - $updated_color_attributes[$key] = $color_attribute; + $color_attribute->addTranslation('fr', [ + 'name' => 'FR ' . $color_attribute->label(), + ]); + $color_attribute->save(); } $size_attributes = $this->createAttributeSet($variation_type, 'size', [ 'small' => 'Small', 'medium' => 'Medium', 'large' => 'Large', ]); - $updated_size_attributes = []; foreach ($size_attributes as $key => $size_attribute) { - $size_attribute_fr = $size_attribute->toArray(); - $size_attribute_fr['name'] = 'FR ' . $size_attribute->label(); - $size_attribute->addTranslation('fr', $size_attribute_fr)->save(); - $updated_size_attributes[$key] = $size_attribute; + $size_attribute->addTranslation('fr', [ + 'name' => 'FR ' . $size_attribute->label(), + ]); + $size_attribute->save(); } // Reload the variation since we have new fields. $this->variation = ProductVariation::load($this->variation->id()); + + // Translate the product's title. $product = $this->variation->getProduct(); - $product->setTitle('Title'); + $product->setTitle('My Super Product'); + $product->addTranslation('fr', [ + 'title' => 'Mon super produit', + ]); $product->save(); - // Add translation. - $product_fr = $product->toArray(); - $product_fr['title'] = 'FR title'; - $product->addTranslation('fr', $product_fr)->save(); // Update first variation to have the attribute's value. - $this->variation->attribute_color = $color_attributes['red']->id(); - $this->variation->attribute_size = $size_attributes['small']->id(); + $this->variation->get('attribute_color')->setValue($color_attributes['red']); + $this->variation->get('attribute_size')->setValue($size_attributes['small']); $this->variation->save(); - - $variation_fr = $this->variation->toArray(); - $this->variation->addTranslation('fr', $variation_fr)->save(); + $this->variation->addTranslation('fr')->save(); // The matrix is intentionally uneven, blue / large is missing. $attribute_values_matrix = [ @@ -127,9 +116,7 @@ public function setUp() { ['blue', 'small'], ['blue', 'medium'], ]; - $variations = [ - $this->variation, - ]; + // Generate variations off of the attributes values matrix. foreach ($attribute_values_matrix as $key => $value) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ @@ -141,29 +128,42 @@ public function setUp() { 'currency_code' => 'USD', ], ]); - $variation->attribute_color = $updated_color_attributes[$value[0]]; - $variation->attribute_size = $updated_size_attributes[$value[1]]; - $variation->save(); - $variation = ProductVariation::load($variation->id()); - $product->variations->appendItem($variation); - $product->save(); - // Add variation FR translation. - $variation_fr = $variation->toArray(); - $variation->addTranslation('fr', $variation_fr)->save(); + $variation->get('attribute_color')->setValue($color_attributes[$value[0]]); + $variation->get('attribute_size')->setValue($size_attributes[$value[1]]); $variation->save(); - $variations[] = $variation; + $variation->addTranslation('fr')->save(); + $product->addVariation($variation); } + $product->save(); $this->product = Product::load($product->id()); $this->variations = $product->getVariations(); - $this->colorAttributes = $updated_color_attributes; - $this->sizeAttributes = $updated_size_attributes; + $this->colorAttributes = $color_attributes; + $this->sizeAttributes = $size_attributes; + } + + /** + * Sets up the multilingual items. + */ + protected function setupMultilingual() { + // Add a new language. + ConfigurableLanguage::createFromLangcode('fr')->save(); + + // Enable translation for the product and ensure the change is picked up. + $this->container->get('content_translation.manager')->setEnabled('commerce_product', $this->variation->bundle(), TRUE); + $this->container->get('content_translation.manager')->setEnabled('commerce_product_variation', $this->variation->bundle(), TRUE); + $this->container->get('entity.manager')->clearCachedDefinitions(); + $this->container->get('router.builder')->rebuild(); + $this->container->get('entity.definition_update_manager')->applyUpdates(); + + // Rebuild the container so that the new languages are picked up by services + // that hold a list of languages. + $this->rebuildContainer(); } /** - * Tests adding a product to the cart using - * 'commerce_product_variation_attributes' widget. + * Tests that the attribute widget uses translated items. */ public function testProductVariationAttributesWidget() { $this->drupalGet($this->product->toUrl()); @@ -204,8 +204,7 @@ public function testProductVariationAttributesWidget() { } /** - * Tests adding a product to the cart using 'commerce_product_variation_title' - * widget. + * Tests the title widget has translated variation title. */ public function testProductVariationTitleWidget() { $order_item_form_display = EntityFormDisplay::load('commerce_order_item.default.add_to_cart'); @@ -216,7 +215,7 @@ public function testProductVariationTitleWidget() { $this->drupalGet($this->product->toUrl()); $this->assertSession()->selectExists('purchased_entity[0][variation]'); - $this->assertAttributeSelected('purchased_entity[0][variation]', 'Title - Red, Small'); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'My Super Product - Red, Small'); $this->getSession()->getPage()->pressButton('Add to cart'); // Change the site language. @@ -224,16 +223,16 @@ public function testProductVariationTitleWidget() { $this->product = Product::load($this->product->id()); $this->drupalGet($this->product->toUrl()); // Use AJAX to change the size to Medium, keeping the color on Red. - $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Red, FR Small'); - $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'FR title - FR Red, FR Medium'); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'Mon super produit - FR Red, FR Small'); + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Mon super produit - FR Red, FR Medium'); $this->waitForAjaxToFinish(); - $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Red, FR Medium'); - $this->assertSession()->pageTextContains('FR title - FR Red, FR Medium'); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'Mon super produit - FR Red, FR Medium'); + $this->assertSession()->pageTextContains('Mon super produit - FR Red, FR Medium'); // Use AJAX to change the color to Blue, keeping the size on Medium. - $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'FR title - FR Blue, FR Medium'); + $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Mon super produit - FR Blue, FR Medium'); $this->waitForAjaxToFinish(); - $this->assertAttributeSelected('purchased_entity[0][variation]', 'FR title - FR Blue, FR Medium'); - $this->assertSession()->pageTextContains('FR title - FR Blue, FR Medium'); + $this->assertAttributeSelected('purchased_entity[0][variation]', 'Mon super produit - FR Blue, FR Medium'); + $this->assertSession()->pageTextContains('Mon super produit - FR Blue, FR Medium'); $this->getSession()->getPage()->pressButton('Add to cart'); $this->cart = Order::load($this->cart->id()); From 71d22bc8b3824142fa69136550f72e7a1d304d4b Mon Sep 17 00:00:00 2001 From: smaz Date: Mon, 23 Oct 2017 07:56:28 -0500 Subject: [PATCH 17/24] Issue #2877632 by smaz: Redirect to Order view instead of Orders listing after order add/edit --- modules/order/src/Form/OrderForm.php | 2 +- modules/order/tests/src/Functional/OrderAdminTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/order/src/Form/OrderForm.php b/modules/order/src/Form/OrderForm.php index c2e1c2749..719ed12e7 100644 --- a/modules/order/src/Form/OrderForm.php +++ b/modules/order/src/Form/OrderForm.php @@ -163,7 +163,7 @@ protected function fieldAsReadOnly($label, $value) { public function save(array $form, FormStateInterface $form_state) { $this->entity->save(); drupal_set_message($this->t('The order %label has been successfully saved.', ['%label' => $this->entity->label()])); - $form_state->setRedirect('entity.commerce_order.collection'); + $form_state->setRedirect('entity.commerce_order.canonical', ['commerce_order' => $this->entity->id()]); } } diff --git a/modules/order/tests/src/Functional/OrderAdminTest.php b/modules/order/tests/src/Functional/OrderAdminTest.php index 2565693a1..4b9451e72 100644 --- a/modules/order/tests/src/Functional/OrderAdminTest.php +++ b/modules/order/tests/src/Functional/OrderAdminTest.php @@ -99,7 +99,7 @@ public function testCreateOrder() { 'adjustments[0][definition][amount][number]' => '2.00', ]; $this->submitForm($edit, 'Save'); - + $this->drupalGet('/admin/commerce/orders'); $order_number = $this->getSession()->getPage()->find('css', 'tr td.views-field-order-number'); $this->assertEquals(1, count($order_number), 'Order exists in the table.'); From 5a5354871d2f2115a58e283433f1ac248fc965d3 Mon Sep 17 00:00:00 2001 From: LiuXin Date: Mon, 23 Oct 2017 10:57:04 -0500 Subject: [PATCH 18/24] Issue #2916252 by caseylau, skyredwang: Order's Adjustment can't be normalized and serialized --- modules/order/commerce_order.services.yml | 5 + .../order/src/Normalizer/AdjustmentNormalizer.php | 51 ++++++++++ .../src/Kernel/AdjustmentItemNormalizeTest.php | 109 +++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 modules/order/src/Normalizer/AdjustmentNormalizer.php create mode 100644 modules/order/tests/src/Kernel/AdjustmentItemNormalizeTest.php diff --git a/modules/order/commerce_order.services.yml b/modules/order/commerce_order.services.yml index 701522828..7c97dbcc3 100644 --- a/modules/order/commerce_order.services.yml +++ b/modules/order/commerce_order.services.yml @@ -62,3 +62,8 @@ services: arguments: ['@current_route_match'] tags: - { name: commerce_store.store_resolver, priority: 100 } + commerce_order.normalizer.adjustment: + class: Drupal\commerce_order\Normalizer\AdjustmentNormalizer + tags: + # This normalizer must just be higher than serializer.normalizer.typed_data, so setting priority as 0 here. + - { name: normalizer, priority: 0} diff --git a/modules/order/src/Normalizer/AdjustmentNormalizer.php b/modules/order/src/Normalizer/AdjustmentNormalizer.php new file mode 100644 index 000000000..77287f8c2 --- /dev/null +++ b/modules/order/src/Normalizer/AdjustmentNormalizer.php @@ -0,0 +1,51 @@ +getValue(); + if ($value instanceof Adjustment) { + return TRUE; + } + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function normalize($object, $format = NULL, array $context = []) { + $attributes = []; + /** @var \Drupal\commerce_order\Adjustment $adjustment */ + $adjustment = $object->getValue(); + $attributes['type'] = $adjustment->getType(); + $attributes['label'] = $adjustment->getLabel(); + $attributes['amount'] = $adjustment->getAmount()->toArray(); + $attributes['percentage'] = $adjustment->getPercentage(); + $attributes['source_id'] = $adjustment->getSourceId(); + $attributes['included'] = $adjustment->isIncluded(); + $attributes['locked'] = $adjustment->isLocked(); + return $attributes; + } + +} diff --git a/modules/order/tests/src/Kernel/AdjustmentItemNormalizeTest.php b/modules/order/tests/src/Kernel/AdjustmentItemNormalizeTest.php new file mode 100644 index 000000000..5be631898 --- /dev/null +++ b/modules/order/tests/src/Kernel/AdjustmentItemNormalizeTest.php @@ -0,0 +1,109 @@ + 'test_adjustments', + 'entity_type' => 'entity_test', + 'type' => 'commerce_adjustment', + 'cardinality' => FieldStorageConfig::CARDINALITY_UNLIMITED, + ]); + $field_storage->save(); + + $field = FieldConfig::create([ + 'field_name' => 'test_adjustments', + 'entity_type' => 'entity_test', + 'bundle' => 'entity_test', + ]); + $field->save(); + + $entity = EntityTest::create([ + 'name' => 'Test', + ]); + $entity->save(); + $this->testEntity = $entity; + + $this->serializer = \Drupal::service('serializer'); + } + + /** + * Tests the normalization of adjustment field. + */ + public function testAdjustmentItemNormalize() { + /** @var \Drupal\Core\Field\FieldItemListInterface $adjustment_item_list */ + $adjustment_item_list = $this->testEntity->test_adjustments; + $adjustment_item_list->appendItem(new Adjustment([ + 'type' => 'custom', + 'label' => '10% off', + 'amount' => new Price('-1.00', 'USD'), + 'percentage' => '0.1', + 'source_id' => '1', + 'included' => FALSE, + 'locked' => TRUE, + ])); + $expected = [ + 0 => [ + 'value' => [ + 'type' => 'custom', + 'label' => '10% off', + 'amount' => [ + 'number' => '-1.00', + 'currency_code' => 'USD', + ], + 'percentage' => '0.1', + 'source_id' => '1', + 'included' => FALSE, + 'locked' => TRUE, + ], + ], + ]; + $normalized = $this->serializer->normalize($adjustment_item_list); + $this->assertSame($expected, $normalized); + } + +} From fe115a3d884a0982898e69a719c8e47023ad2059 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 13:07:26 -0500 Subject: [PATCH 19/24] Try flushing caches --- .../cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index 3b1373576..f7c664920 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -176,6 +176,7 @@ public function testProductVariationAttributesWidget() { // Change the site language. $this->config('system.site')->set('default_langcode', 'fr')->save(); + drupal_flush_all_caches(); $this->drupalGet($this->product->toUrl()); // Use AJAX to change the size to Medium, keeping the color on Red. From a4fe89038eea440dd4fcf1811b02be866c227319 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 13:38:00 -0500 Subject: [PATCH 20/24] Link to proper product --- .../tests/src/FunctionalJavascript/AddToCartMultilingualTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index f7c664920..53c934b6a 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -178,7 +178,7 @@ public function testProductVariationAttributesWidget() { $this->config('system.site')->set('default_langcode', 'fr')->save(); drupal_flush_all_caches(); - $this->drupalGet($this->product->toUrl()); + $this->drupalGet($this->product->getTranslation('fr')->toUrl()); // Use AJAX to change the size to Medium, keeping the color on Red. $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][attributes][attribute_size]', 'FR Medium'); $this->waitForAjaxToFinish(); @@ -221,8 +221,9 @@ public function testProductVariationTitleWidget() { // Change the site language. $this->config('system.site')->set('default_langcode', 'fr')->save(); - $this->product = Product::load($this->product->id()); - $this->drupalGet($this->product->toUrl()); + drupal_flush_all_caches(); + + $this->drupalGet($this->product->getTranslation('fr')->toUrl()); // Use AJAX to change the size to Medium, keeping the color on Red. $this->assertAttributeSelected('purchased_entity[0][variation]', 'Mon super produit - FR Red, FR Small'); $this->getSession()->getPage()->selectFieldOption('purchased_entity[0][variation]', 'Mon super produit - FR Red, FR Medium'); From 3ac4f0f9fc75fb08feb2d2835a04e5cf26c0dc92 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 15:01:28 -0500 Subject: [PATCH 21/24] Fix failing test --- .../tests/src/FunctionalJavascript/AddToCartMultilingualTest.php | 7 +++++-- .../src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php | 6 ++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php index 53c934b6a..98f9ee489 100644 --- a/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php +++ b/modules/cart/tests/src/FunctionalJavascript/AddToCartMultilingualTest.php @@ -106,7 +106,6 @@ public function setUp() { $this->variation->get('attribute_color')->setValue($color_attributes['red']); $this->variation->get('attribute_size')->setValue($size_attributes['small']); $this->variation->save(); - $this->variation->addTranslation('fr')->save(); // The matrix is intentionally uneven, blue / large is missing. $attribute_values_matrix = [ @@ -131,13 +130,17 @@ public function setUp() { $variation->get('attribute_color')->setValue($color_attributes[$value[0]]); $variation->get('attribute_size')->setValue($size_attributes[$value[1]]); $variation->save(); - $variation->addTranslation('fr')->save(); $product->addVariation($variation); } $product->save(); $this->product = Product::load($product->id()); + // Create a translation for each variation on the product. + foreach ($this->product->getVariations() as $variation) { + $variation->addTranslation('fr')->save(); + } + $this->variations = $product->getVariations(); $this->colorAttributes = $color_attributes; $this->sizeAttributes = $size_attributes; diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php index 682fed720..e80a41a80 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php @@ -72,10 +72,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $form_state->get('product'); /** @var \Drupal\commerce_product\Entity\ProductVariationInterface[] $variations */ - $variations = []; - foreach ($product->getVariations() as $variation) { - $variations[] = $variation; - } + $variations = $this->variationStorage->loadEnabled($product); + if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. $form_state->set('hide_form', TRUE); From 27e086049e5f4a307f659d1211a7d7d4d0ae2f92 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 23 Oct 2017 15:29:34 -0500 Subject: [PATCH 22/24] Few nits and fixes. --- modules/checkout/tests/src/Functional/CheckoutOrderTest.php | 8 ++++---- modules/order/src/Entity/Order.php | 3 +-- modules/order/src/Entity/OrderItem.php | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/checkout/tests/src/Functional/CheckoutOrderTest.php b/modules/checkout/tests/src/Functional/CheckoutOrderTest.php index 13e10c58c..7ed0ccbc5 100644 --- a/modules/checkout/tests/src/Functional/CheckoutOrderTest.php +++ b/modules/checkout/tests/src/Functional/CheckoutOrderTest.php @@ -135,7 +135,7 @@ public function testCacheMetadata() { */ public function testGuestOrderCheckout() { $this->drupalLogout(); - $this->drupalGet($this->product->toUrl()); + $this->drupalGet($this->product->toUrl()->toString()); $this->submitForm([], 'Add to cart'); $this->assertSession()->pageTextContains('1 item'); $cart_link = $this->getSession()->getPage()->findLink('your cart'); @@ -165,7 +165,7 @@ public function testGuestOrderCheckout() { $this->assertSession()->pageTextContains('Your order number is 1. You can view your order on your account page when logged in.'); $this->assertSession()->pageTextContains('0 items'); // Test second order. - $this->drupalGet($this->product->toUrl()); + $this->drupalGet($this->product->toUrl()->toString()); $this->submitForm([], 'Add to cart'); $this->assertSession()->pageTextContains('1 item'); $cart_link = $this->getSession()->getPage()->findLink('your cart'); @@ -212,7 +212,7 @@ public function testRegisterOrderCheckout() { $config->save(); $this->drupalLogout(); - $this->drupalGet($this->product->toUrl()); + $this->drupalGet($this->product->toUrl()->toString()); $this->submitForm([], 'Add to cart'); $cart_link = $this->getSession()->getPage()->findLink('your cart'); $cart_link->click(); @@ -325,7 +325,7 @@ public function testCheckoutFlowOnCartUpdate() { 'stores' => [$this->store], ]); // Adding a new product to the cart resets the checkout step. - $this->drupalGet($product2->toUrl()); + $this->drupalGet($product2->toUrl()->toString()); $this->submitForm([], 'Add to cart'); $this->getSession()->getPage()->findLink('your cart')->click(); $this->submitForm([], 'Checkout'); diff --git a/modules/order/src/Entity/Order.php b/modules/order/src/Entity/Order.php index 13cf999c4..99eb6bef5 100644 --- a/modules/order/src/Entity/Order.php +++ b/modules/order/src/Entity/Order.php @@ -91,8 +91,7 @@ public function setOrderNumber($order_number) { * {@inheritdoc} */ public function getStore() { - $store = $this->getTranslatedReferencedEntities('store_id'); - return reset($store); + return $this->getTranslatedReferencedEntity('store_id'); } /** diff --git a/modules/order/src/Entity/OrderItem.php b/modules/order/src/Entity/OrderItem.php index d4d7ea778..3ee87c99f 100644 --- a/modules/order/src/Entity/OrderItem.php +++ b/modules/order/src/Entity/OrderItem.php @@ -75,8 +75,7 @@ public function hasPurchasedEntity() { * {@inheritdoc} */ public function getPurchasedEntity() { - $purchased_entity = $this->getTranslatedReferencedEntities('purchased_entity'); - return reset($purchased_entity); + return $this->getTranslatedReferencedEntity('purchased_entity'); } /** From 6d7bd73263c813dd1d16ac85acd17ea394256032 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 6 Nov 2017 16:54:53 -0600 Subject: [PATCH 23/24] Remove unneeded changes --- modules/product/src/Entity/Product.php | 2 +- modules/product/src/Entity/ProductVariation.php | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/product/src/Entity/Product.php b/modules/product/src/Entity/Product.php index 439a9663a..f2469355f 100644 --- a/modules/product/src/Entity/Product.php +++ b/modules/product/src/Entity/Product.php @@ -251,7 +251,7 @@ public function getDefaultVariation() { foreach ($this->getVariations() as $variation) { // Return the first active variation. if ($variation->isActive() && $variation->access('view')) { - return $variation->getTranslation($this->language()->getId()); + return $variation; } } } diff --git a/modules/product/src/Entity/ProductVariation.php b/modules/product/src/Entity/ProductVariation.php index 4ab0fe25e..249caca73 100644 --- a/modules/product/src/Entity/ProductVariation.php +++ b/modules/product/src/Entity/ProductVariation.php @@ -288,10 +288,7 @@ public function getAttributeValues() { foreach ($this->getAttributeFieldNames() as $field_name) { $field = $this->get($field_name); if (!$field->isEmpty()) { - /** @var \Drupal\commerce_product\Entity\ProductAttributeValueInterface $entity */ - $entity = $field->entity; - $attribute_value = $entity->getTranslation($this->language()->getId()); - $attribute_values[$field_name] = $attribute_value; + $attribute_values[$field_name] = $field->entity; } } @@ -360,6 +357,7 @@ protected function generateTitle() { // When there are no attribute fields, there's only one variation. $title = $product_title; } + return $title; } From 12939a69e642c0107fa0bd4f109437d82578298b Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Mon, 6 Nov 2017 16:56:50 -0600 Subject: [PATCH 24/24] Undo changes to variation title widget --- .../src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php index e80a41a80..e6a95d672 100644 --- a/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php +++ b/modules/product/src/Plugin/Field/FieldWidget/ProductVariationTitleWidget.php @@ -73,7 +73,6 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $product = $form_state->get('product'); /** @var \Drupal\commerce_product\Entity\ProductVariationInterface[] $variations */ $variations = $this->variationStorage->loadEnabled($product); - if (count($variations) === 0) { // Nothing to purchase, tell the parent form to hide itself. $form_state->set('hide_form', TRUE); @@ -153,8 +152,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen * The selected variation. */ protected function selectVariationFromUserInput(array $variations, array $user_input) { - $current_variation = reset($variations); - if (!empty($user_input) && !empty($user_input['variation']) && $variations[$user_input['variation']]) { + $current_variation = NULL; + if (!empty($user_input['variation']) && $variations[$user_input['variation']]) { $current_variation = $variations[$user_input['variation']]; }