From 42d5ef9c38cb4c97652f4774ece446641d3f2ab2 Mon Sep 17 00:00:00 2001 From: Oleksandr Melnyk Date: Wed, 6 Jan 2021 18:05:00 +0200 Subject: [PATCH 01/40] magento/magento2#31332:Implement the schema changes for Configurable Options Selection - resolved fields according to the new schema --- .../Products/DataProvider/ProductSearch.php | 10 ++ .../Model/Formatter/Option.php | 62 ++++++++ .../Model/Formatter/OptionValue.php | 65 ++++++++ .../Model/Formatter/Variant.php | 49 ++++++ .../Model/Options/DataProvider/Variant.php | 10 +- .../Model/Options/Metadata.php | 141 ++++-------------- .../Model/Options/SelectionUidFormatter.php | 29 +++- .../Model/Resolver/OptionsSelection.php | 97 ++++++++++++ .../Model/Resolver/SelectionMediaGallery.php | 28 +++- .../ConfigurableProductGraphQl/composer.json | 1 + .../ConfigurableProductGraphQl/etc/module.xml | 1 + .../etc/schema.graphqls | 30 +++- 12 files changed, 390 insertions(+), 133 deletions(-) create mode 100644 app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php create mode 100644 app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php create mode 100644 app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Variant.php create mode 100644 app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php index 13bd29e83d87f..4350875ccca7c 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php @@ -18,6 +18,8 @@ use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Api\SearchResultsInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\GraphQl\Model\Query\ContextInterface; /** @@ -87,6 +89,7 @@ public function __construct( * @param array $attributes * @param ContextInterface|null $context * @return SearchResultsInterface + * @throws GraphQlNoSuchEntityException */ public function getList( SearchCriteriaInterface $searchCriteria, @@ -107,6 +110,13 @@ public function getList( )->apply(); $this->collectionPreProcessor->process($collection, $searchCriteriaForCollection, $attributes, $context); + + try { + $collection->addMediaGalleryData(); + } catch (LocalizedException $e) { + throw new GraphQlNoSuchEntityException(__('Cannot load media galery')); + } + $collection->load(); $this->collectionPostProcessor->process($collection, $attributes); diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php new file mode 100644 index 0000000000000..240dca5def4cf --- /dev/null +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php @@ -0,0 +1,62 @@ +idEncoder = $idEncoder; + $this->valueFormatter = $valueFormatter; + } + + /** + * Format configurable product options according to the GraphQL schema + * + * @param Attribute $attribute + * @return array|null + */ + public function format(Attribute $attribute): ?array + { + $optionValues = []; + + foreach ($attribute->getOptions() as $option) { + $optionValues[] = $this->valueFormatter->format($option, $attribute); + } + + return [ + 'uid' => $this->idEncoder->encode($attribute->getProductSuperAttributeId()), + 'attribute_code' => $attribute->getProductAttribute()->getAttributeCode(), + 'label' => $attribute->getLabel(), + 'values' => $optionValues, + ]; + } +} diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php new file mode 100644 index 0000000000000..3a991c3bca635 --- /dev/null +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php @@ -0,0 +1,65 @@ +selectionUidFormatter = $selectionUidFormatter; + $this->swatchDataProvider = $swatchDataProvider; + } + + /** + * Format configurable product option values according to the GraphQL schema + * + * @param array $optionValue + * @param Attribute $attribute + * @return array + */ + public function format(array $optionValue, Attribute $attribute): array + { + $valueIndex = (int)$optionValue['value_index']; + $attributeId = (int)$attribute->getAttributeId(); + + return [ + 'uid' => $this->selectionUidFormatter->encode( + $attributeId, + $valueIndex + ), + 'is_available' => true, + 'is_default' => (bool)$attribute->getIsUseDefault(), + 'label' => $optionValue['label'], + 'swatch' => $this->swatchDataProvider->getData($optionValue['value_index']) + ]; + } +} diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Variant.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Variant.php new file mode 100644 index 0000000000000..1d73ad6a19336 --- /dev/null +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Variant.php @@ -0,0 +1,49 @@ + $selectedValue) { + if (!isset($options[$attributeId][$selectedValue])) { + throw new GraphQlInputException(__('configurableOptionValueUids values are incorrect')); + } + + $productIds = array_intersect($productIds, $options[$attributeId][$selectedValue]); + } + + if (count($productIds) === 1) { + $variantProduct = $variants[array_pop($productIds)]; + $variant = $variantProduct->getData(); + $variant['url_path'] = $variantProduct->getProductUrl(); + $variant['model'] = $variantProduct; + } + + return $variant; + } +} diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php index 80fbdc76bacb3..71671353facf5 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php @@ -10,6 +10,8 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\Framework\DataObject; +use Magento\Framework\Exception\LocalizedException; /** * Retrieve child products @@ -42,10 +44,10 @@ public function __construct( * Load available child products by parent * * @param ProductInterface $product - * @return ProductInterface[] - * @throws \Magento\Framework\Exception\LocalizedException + * @return DataObject[] + * @throws LocalizedException */ - public function getSalableVariantsByParent(ProductInterface $product) + public function getSalableVariantsByParent(ProductInterface $product): array { $collection = $this->configurableType->getUsedProductCollection($product); $collection @@ -62,6 +64,6 @@ public function getSalableVariantsByParent(ProductInterface $product) } $collection->clear(); - return $collection->getItems(); + return $collection->getItems() ?? []; } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php index 9fa6e4f23fa56..92bfe61ee9b2d 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php @@ -3,15 +3,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + declare(strict_types=1); namespace Magento\ConfigurableProductGraphQl\Model\Options; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\ConfigurableProduct\Helper\Data; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute; +use Magento\ConfigurableProductGraphQl\Model\Formatter\Option; use Magento\ConfigurableProductGraphQl\Model\Options\DataProvider\Variant; -use Magento\Framework\Exception\NoSuchEntityException; +use Magento\ConfigurableProductGraphQl\Model\Formatter\Variant as VariantFormatter; /** * Retrieve metadata for configurable option selection. @@ -24,150 +26,63 @@ class Metadata private $configurableProductHelper; /** - * @var SelectionUidFormatter - */ - private $selectionUidFormatter; - - /** - * @var ProductRepositoryInterface + * @var Option */ - private $productRepository; - - /** - * @var Variant - */ - private $variant; + private $configurableOptionsFormatter; /** * @param Data $configurableProductHelper - * @param SelectionUidFormatter $selectionUidFormatter - * @param ProductRepositoryInterface $productRepository - * @param Variant $variant + * @param Option $configurableOptionsFormatter */ public function __construct( Data $configurableProductHelper, - SelectionUidFormatter $selectionUidFormatter, - ProductRepositoryInterface $productRepository, - Variant $variant + Option $configurableOptionsFormatter + ) { $this->configurableProductHelper = $configurableProductHelper; - $this->selectionUidFormatter = $selectionUidFormatter; - $this->productRepository = $productRepository; - $this->variant = $variant; + $this->configurableOptionsFormatter = $configurableOptionsFormatter; } /** - * Load available selections from configurable options. + * Load available selections from configurable options and variant. * * @param ProductInterface $product - * @param array $selectedOptionsUid + * @param array $options + * @param array $selectedOptions * @return array - * @throws NoSuchEntityException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function getAvailableSelections( - ProductInterface $product, - array $selectedOptionsUid - ): array { - $options = $this->configurableProductHelper->getOptions($product, $this->getAllowProducts($product)); - $selectedOptions = $this->selectionUidFormatter->extract($selectedOptionsUid); - $attributeCodes = $this->getAttributeCodes($product); - $availableSelections = $availableProducts = $variantData = []; - - if (isset($options['index']) && $options['index']) { - foreach ($options['index'] as $productId => $productOptions) { - if (!empty($selectedOptions) && !$this->hasProductRequiredOptions($selectedOptions, $productOptions)) { - continue; - } - - $availableProducts[] = $productId; - foreach ($productOptions as $attributeId => $optionIndex) { - $uid = $this->selectionUidFormatter->encode($attributeId, (int)$optionIndex); + public function getAvailableSelections(ProductInterface $product, array $options, array $selectedOptions): array + { + $attributes = $this->getAttributes($product); - if (isset($availableSelections[$attributeId]['option_value_uids']) - && in_array($uid, $availableSelections[$attributeId]['option_value_uids']) - ) { - continue; - } - $availableSelections[$attributeId]['option_value_uids'][] = $uid; - $availableSelections[$attributeId]['attribute_code'] = $attributeCodes[$attributeId]; - } + $availableSelections = []; - if ($this->hasSelectionProduct($selectedOptions, $productOptions)) { - $variantProduct = $this->productRepository->getById($productId); - $variantData = $variantProduct->getData(); - $variantData['model'] = $variantProduct; - } + foreach ($options as $attributeId => $option) { + if ($attributeId === 'index' || isset($selectedOptions[$attributeId])) { + continue; } - } - return [ - 'options_available_for_selection' => $availableSelections, - 'variant' => $variantData, - 'availableSelectionProducts' => array_unique($availableProducts), - 'product' => $product - ]; - } - - /** - * Get allowed products. - * - * @param ProductInterface $product - * @return ProductInterface[] - */ - public function getAllowProducts(ProductInterface $product): array - { - return $this->variant->getSalableVariantsByParent($product) ?? []; - } - - /** - * Check if a product has the selected options. - * - * @param array $requiredOptions - * @param array $productOptions - * @return bool - */ - private function hasProductRequiredOptions($requiredOptions, $productOptions): bool - { - $result = true; - foreach ($requiredOptions as $attributeId => $optionIndex) { - if (!isset($productOptions[$attributeId]) || !$productOptions[$attributeId] - || $optionIndex != $productOptions[$attributeId] - ) { - $result = false; - break; - } + $availableSelections[] = $this->configurableOptionsFormatter->format($attributes[$attributeId]); } - return $result; - } + return $availableSelections; - /** - * Check if selected options match a product. - * - * @param array $requiredOptions - * @param array $productOptions - * @return bool - */ - private function hasSelectionProduct($requiredOptions, $productOptions): bool - { - return $this->hasProductRequiredOptions($productOptions, $requiredOptions); } /** - * Retrieve attribute codes + * Retrieve configurable attributes for the product * * @param ProductInterface $product - * @return string[] + * @return Attribute[] */ - private function getAttributeCodes(ProductInterface $product): array + private function getAttributes(ProductInterface $product): array { $allowedAttributes = $this->configurableProductHelper->getAllowAttributes($product); - $attributeCodes = []; + $attributes = []; foreach ($allowedAttributes as $attribute) { - $attributeCodes[$attribute->getAttributeId()] = $attribute->getProductAttribute()->getAttributeCode(); + $attributes[$attribute->getAttributeId()] = $attribute; } - return $attributeCodes; + return $attributes; } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php index 1d13ad75489a1..7bcf08a9b9509 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php @@ -3,8 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProductGraphQl\Model\Options; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Query\Uid; + /** * Handle option selection uid. */ @@ -20,6 +24,19 @@ class SelectionUidFormatter */ private const UID_SEPARATOR = '/'; + /** + * @var Uid + */ + private $idEncoder; + + /** + * @param Uid $idEncoder + */ + public function __construct(Uid $idEncoder) + { + $this->idEncoder = $idEncoder; + } + /** * Create uid and encode. * @@ -29,8 +46,7 @@ class SelectionUidFormatter */ public function encode(int $attributeId, int $indexId): string { - // phpcs:ignore Magento2.Functions.DiscouragedFunction - return base64_encode(implode(self::UID_SEPARATOR, [ + return $this->idEncoder->encode(implode(self::UID_SEPARATOR, [ self::UID_PREFIX, $attributeId, $indexId @@ -40,17 +56,16 @@ public function encode(int $attributeId, int $indexId): string /** * Retrieve attribute and option index from uid. Array key is the id of attribute and value is the index of option * - * @param string $selectionUids + * @param array $selectionUids * @return array - * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @throws GraphQlInputException */ public function extract(array $selectionUids): array { $attributeOption = []; foreach ($selectionUids as $uid) { - // phpcs:ignore Magento2.Functions.DiscouragedFunction - $optionData = explode(self::UID_SEPARATOR, base64_decode($uid)); - if (count($optionData) == 3) { + $optionData = explode(self::UID_SEPARATOR, $this->idEncoder->decode($uid)); + if (count($optionData) === 3) { $attributeOption[(int)$optionData[1]] = (int)$optionData[2]; } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php new file mode 100644 index 0000000000000..6d1e4cbf5bb00 --- /dev/null +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php @@ -0,0 +1,97 @@ +configurableSelectionMetadata = $configurableSelectionMetadata; + $this->selectionUidFormatter = $selectionUidFormatter; + $this->variant = $variant; + $this->variantFormatter = $variantFormatter; + $this->configurableProductHelper = $configurableProductHelper; + } + + /** + * @inheritDoc + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + if (!isset($value['model'])) { + throw new LocalizedException(__('"model" value should be specified')); + } + + $product = $value['model']; + + $selectionUids = $args['configurableOptionValueUids'] ?? []; + $selectedOptions = $this->selectionUidFormatter->extract($selectionUids); + + $variants = $this->variant->getSalableVariantsByParent($product); + $options = $this->configurableProductHelper->getOptions($product, $variants); + + return [ + 'configurable_options' => $this->configurableSelectionMetadata->getAvailableSelections( + $product, + $options, + $selectedOptions + ), + 'variant' => $this->variantFormatter->format($options, $selectedOptions, $variants), + 'model' => $product + ]; + } +} diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php index 7b3ddc4ac1417..b6e7574fc20d8 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php @@ -30,8 +30,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value foreach ($usedProducts as $usedProduct) { if (in_array($usedProduct->getId(), $availableSelectionProducts)) { foreach ($usedProduct->getMediaGalleryEntries() ?? [] as $key => $entry) { - $index = $usedProduct->getId() . '_' . $key; - $mediaGalleryEntries[$index] = $entry->getData(); + $entryData = $entry->getData(); + $initialIndex = $usedProduct->getId() . '_' . $key; + $index = $this->prepareIndex($entryData, $initialIndex); + $mediaGalleryEntries[$index] = $entryData; $mediaGalleryEntries[$index]['model'] = $usedProduct; if ($entry->getExtensionAttributes() && $entry->getExtensionAttributes()->getVideoContent()) { $mediaGalleryEntries[$index]['video_content'] @@ -42,4 +44,26 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } return $mediaGalleryEntries; } + + /** + * Formulate an index to have unique set of media entries + * + * @param array $entryData + * @param string $initialIndex + * @return string + */ + private function prepareIndex(array $entryData, string $initialIndex) : string + { + $index = $initialIndex; + if (isset($entryData['media_type'])) { + $index = $entryData['media_type']; + } + if (isset($entryData['file'])) { + $index = $index.'_'.$entryData['file']; + } + if (isset($entryData['position'])) { + $index = $index.'_'.$entryData['position']; + } + return $index; + } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/composer.json b/app/code/Magento/ConfigurableProductGraphQl/composer.json index a6e1d1c822435..72ecdbc3a375f 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/composer.json +++ b/app/code/Magento/ConfigurableProductGraphQl/composer.json @@ -11,6 +11,7 @@ "magento/module-quote": "*", "magento/module-quote-graph-ql": "*", "magento/module-catalog-inventory": "*", + "magento/module-swatches-graph-ql": "*", "magento/framework": "*" }, "license": [ diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml b/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml index 3aa1658c9388d..e6345ac188631 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml @@ -14,6 +14,7 @@ + diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index fc177557906ee..dcfcc426f239c 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -7,7 +7,29 @@ type Mutation { type ConfigurableProduct implements ProductInterface, PhysicalProductInterface, CustomizableProductInterface @doc(description: "ConfigurableProduct defines basic features of a configurable product and its simple product variants") { variants: [ConfigurableVariant] @doc(description: "An array of variants of products") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\ConfigurableVariant") configurable_options: [ConfigurableProductOptions] @doc(description: "An array of linked simple product items") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\Options") - configurable_options_selection_metadata(selectedConfigurableOptionValues: [ID!]): ConfigurableOptionsSelectionMetadata @doc(description: "Metadata for the specified configurable options selection") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\OptionsSelectionMetadata") + configurable_product_options_selection(configurableOptionValueUids: [ID!]): ConfigurableProductOptionsSelection @doc(description: "Specified configurable product options selection") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\OptionsSelection") +} + +type ConfigurableProductOptionsSelection @doc(description: "Metadata corresponding to the configurable options selection.") +{ + configurable_options: [ConfigurableProductOption!] @doc(description: "Configurable options available for further selection based on current selection.") + media_gallery: [MediaGalleryInterface!] @doc(description: "Product images and videos corresponding to the specified configurable options selection.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGallery") + variant: SimpleProduct @doc(description: "Variant represented by the specified configurable options selection. It is expected to be null, until selections are made for each configurable option.") +} + +type ConfigurableProductOption { + uid: ID! + attribute_code: String! + label: String! + values: [ConfigurableProductOptionValue!] +} + +type ConfigurableProductOptionValue { + uid: ID! + is_available: Boolean! + is_use_default: Boolean! + label: String! + swatch: SwatchDataInterface } type ConfigurableVariant @doc(description: "An array containing all the simple product variants of a configurable product") { @@ -80,12 +102,6 @@ type ConfigurableWishlistItem implements WishlistItemInterface @doc(description: configurable_options: [SelectedConfigurableOption!] @resolver(class: "\\Magento\\ConfigurableProductGraphQl\\Model\\Wishlist\\ConfigurableOptions") @doc (description: "An array of selected configurable options") } -type ConfigurableOptionsSelectionMetadata @doc(description: "Metadata corresponding to the configurable options selection.") { - options_available_for_selection: [ConfigurableOptionAvailableForSelection!] @doc(description: "Configurable options available for further selection based on current selection.") - media_gallery: [MediaGalleryInterface!] @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\SelectionMediaGallery") @doc(description: "Product images and videos corresponding to the specified configurable options selection.") - variant: SimpleProduct @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\Variant\\Variant") @doc(description: "Variant represented by the specified configurable options selection. It is expected to be null, until selections are made for each configurable option.") -} - type ConfigurableOptionAvailableForSelection @doc(description: "Configurable option available for further selection based on current selection.") { option_value_uids: [ID!]! @doc(description: "Configurable option values available for further selection.") attribute_code: String! @doc(description: "Attribute code that uniquely identifies configurable option.") From 55f90b4c5c094914a3ed2b1efddbc07c75ea9089 Mon Sep 17 00:00:00 2001 From: Oleksandr Melnyk Date: Tue, 12 Jan 2021 17:09:01 +0200 Subject: [PATCH 02/40] magento/magento2#31332:Schema changes implementation for configurable options selection - added test coverage --- .../Products/DataProvider/ProductSearch.php | 2 +- .../Model/Formatter/Option.php | 5 +- .../Model/Formatter/OptionValue.php | 35 +- .../Model/Options/Metadata.php | 10 +- .../Resolver/OptionsSelectionMetadata.php | 49 --- .../etc/schema.graphqls | 5 - ...nfigurableOptionsSelectionMetadataTest.php | 410 ------------------ .../ConfigurableOptionsSelectionTest.php | 348 +++++++++++++++ 8 files changed, 387 insertions(+), 477 deletions(-) delete mode 100644 app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionMetadataTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php index 4350875ccca7c..bcf0aa15b9e63 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php @@ -114,7 +114,7 @@ public function getList( try { $collection->addMediaGalleryData(); } catch (LocalizedException $e) { - throw new GraphQlNoSuchEntityException(__('Cannot load media galery')); + throw new GraphQlNoSuchEntityException(__('Cannot load media gallery')); } $collection->load(); diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php index 240dca5def4cf..68968b6f3819a 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/Option.php @@ -42,14 +42,15 @@ public function __construct( * Format configurable product options according to the GraphQL schema * * @param Attribute $attribute + * @param array $optionIds * @return array|null */ - public function format(Attribute $attribute): ?array + public function format(Attribute $attribute, array $optionIds): ?array { $optionValues = []; foreach ($attribute->getOptions() as $option) { - $optionValues[] = $this->valueFormatter->format($option, $attribute); + $optionValues[] = $this->valueFormatter->format($option, $attribute, $optionIds); } return [ diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php index 3a991c3bca635..f171514a37897 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php @@ -8,6 +8,7 @@ namespace Magento\ConfigurableProductGraphQl\Model\Formatter; +use Magento\CatalogInventory\Model\StockRegistry; use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute; use Magento\ConfigurableProductGraphQl\Model\Options\SelectionUidFormatter; use Magento\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider\SwatchDataProvider; @@ -27,16 +28,24 @@ class OptionValue */ private $swatchDataProvider; + /** + * @var StockRegistry + */ + private $stockRegistry; + /** * @param SelectionUidFormatter $selectionUidFormatter * @param SwatchDataProvider $swatchDataProvider + * @param StockRegistry $stockRegistry */ public function __construct( SelectionUidFormatter $selectionUidFormatter, - SwatchDataProvider $swatchDataProvider + SwatchDataProvider $swatchDataProvider, + StockRegistry $stockRegistry ) { $this->selectionUidFormatter = $selectionUidFormatter; $this->swatchDataProvider = $swatchDataProvider; + $this->stockRegistry = $stockRegistry; } /** @@ -44,9 +53,10 @@ public function __construct( * * @param array $optionValue * @param Attribute $attribute + * @param array $optionIds * @return array */ - public function format(array $optionValue, Attribute $attribute): array + public function format(array $optionValue, Attribute $attribute, array $optionIds): array { $valueIndex = (int)$optionValue['value_index']; $attributeId = (int)$attribute->getAttributeId(); @@ -56,10 +66,27 @@ public function format(array $optionValue, Attribute $attribute): array $attributeId, $valueIndex ), - 'is_available' => true, - 'is_default' => (bool)$attribute->getIsUseDefault(), + 'is_available' => $this->getIsAvailable($optionIds[$valueIndex] ?? []), + 'is_use_default' => (bool)$attribute->getIsUseDefault(), 'label' => $optionValue['label'], 'swatch' => $this->swatchDataProvider->getData($optionValue['value_index']) ]; } + + /** + * Get is variants available + * + * @param array $variantIds + * @return bool + */ + private function getIsAvailable(array $variantIds): bool + { + foreach ($variantIds as $variantId) { + if ($this->stockRegistry->getProductStockStatus($variantId)) { + return true; + } + } + + return false; + } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php index 92bfe61ee9b2d..5e0c5535c564c 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php @@ -12,8 +12,6 @@ use Magento\ConfigurableProduct\Helper\Data; use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute; use Magento\ConfigurableProductGraphQl\Model\Formatter\Option; -use Magento\ConfigurableProductGraphQl\Model\Options\DataProvider\Variant; -use Magento\ConfigurableProductGraphQl\Model\Formatter\Variant as VariantFormatter; /** * Retrieve metadata for configurable option selection. @@ -37,7 +35,6 @@ class Metadata public function __construct( Data $configurableProductHelper, Option $configurableOptionsFormatter - ) { $this->configurableProductHelper = $configurableProductHelper; $this->configurableOptionsFormatter = $configurableOptionsFormatter; @@ -54,7 +51,6 @@ public function __construct( public function getAvailableSelections(ProductInterface $product, array $options, array $selectedOptions): array { $attributes = $this->getAttributes($product); - $availableSelections = []; foreach ($options as $attributeId => $option) { @@ -62,11 +58,13 @@ public function getAvailableSelections(ProductInterface $product, array $options continue; } - $availableSelections[] = $this->configurableOptionsFormatter->format($attributes[$attributeId]); + $availableSelections[] = $this->configurableOptionsFormatter->format( + $attributes[$attributeId], + $options[$attributeId] ?? [] + ); } return $availableSelections; - } /** diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php deleted file mode 100644 index f7d5a96ad2aba..0000000000000 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php +++ /dev/null @@ -1,49 +0,0 @@ -configurableSelectionMetadata = $configurableSelectionMetadata; - } - - /** - * @inheritDoc - */ - public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) - { - if (!isset($value['model'])) { - throw new LocalizedException(__('"model" value should be specified')); - } - - $selectedOptions = $args['selectedConfigurableOptionValues'] ?? []; - /** @var ProductInterface $product */ - $product = $value['model']; - - return $this->configurableSelectionMetadata->getAvailableSelections($product, $selectedOptions); - } -} diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index dcfcc426f239c..d9e65927a7d52 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -102,11 +102,6 @@ type ConfigurableWishlistItem implements WishlistItemInterface @doc(description: configurable_options: [SelectedConfigurableOption!] @resolver(class: "\\Magento\\ConfigurableProductGraphQl\\Model\\Wishlist\\ConfigurableOptions") @doc (description: "An array of selected configurable options") } -type ConfigurableOptionAvailableForSelection @doc(description: "Configurable option available for further selection based on current selection.") { - option_value_uids: [ID!]! @doc(description: "Configurable option values available for further selection.") - attribute_code: String! @doc(description: "Attribute code that uniquely identifies configurable option.") -} - type StoreConfig @doc(description: "The type contains information about a store config") { configurable_thumbnail_source : String @doc(description: "The configuration setting determines which thumbnail should be used in the cart for configurable products.") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionMetadataTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionMetadataTest.php deleted file mode 100644 index f0e4df50794a3..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionMetadataTest.php +++ /dev/null @@ -1,410 +0,0 @@ -attributeRepository = Bootstrap::getObjectManager()->create(AttributeRepository::class); - $this->selectionUidFormatter = Bootstrap::getObjectManager()->create(SelectionUidFormatter::class); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php - */ - public function testWithoutSelectedOption() - { - $query = <<graphQlQuery($query); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertEquals(2, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'])); - $this->assertEquals(4, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][0]['option_value_uids'])); - $this->assertEquals(4, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][1]['option_value_uids'])); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php - */ - public function testSelectedFirstAttributeFirstOption() - { - $attribute = $this->getFirstConfigurableAttribute(); - $options = $attribute->getOptions(); - $firstOptionUid = $this->selectionUidFormatter->encode( - (int)$attribute->getAttributeId(), - (int)$options[1]->getValue() - ); - $query = <<graphQlQuery($query); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertEquals(2, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'])); - $this->assertEquals(1, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][0]['option_value_uids'])); - $this->assertEquals($firstOptionUid, $response['products']['items'][0] - ['configurable_options_selection_metadata']['options_available_for_selection'][0]['option_value_uids'][0]); - $this->assertEquals(4, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][1]['option_value_uids'])); - - $secondAttributeOptions = $this->getSecondConfigurableAttribute()->getOptions(); - $this->assertAvailableOptionUids( - $this->getSecondConfigurableAttribute()->getAttributeId(), - $secondAttributeOptions, - $response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][1]['option_value_uids'] - ); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php - */ - public function testSelectedFirstAttributeLastOption() - { - $attribute = $this->getFirstConfigurableAttribute(); - $options = $attribute->getOptions(); - $lastOptionUid = $this->selectionUidFormatter->encode( - (int)$attribute->getAttributeId(), - (int)$options[4]->getValue() - ); - $query = <<graphQlQuery($query); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertEquals(2, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'])); - $this->assertEquals(1, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][0]['option_value_uids'])); - $this->assertEquals($lastOptionUid, $response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][0]['option_value_uids'][0]); - $this->assertEquals(2, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][1]['option_value_uids'])); - $secondAttributeOptions = $this->getSecondConfigurableAttribute()->getOptions(); - unset($secondAttributeOptions[0]); - unset($secondAttributeOptions[1]); - unset($secondAttributeOptions[2]); - $this->assertAvailableOptionUids( - $this->getSecondConfigurableAttribute()->getAttributeId(), - $secondAttributeOptions, - $response['products']['items'][0]['configurable_options_selection_metadata'] - ['options_available_for_selection'][1]['option_value_uids'] - ); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php - */ - public function testSelectedVariant() - { - $firstAttribute = $this->getFirstConfigurableAttribute(); - $firstOptions = $firstAttribute->getOptions(); - $firstAttributeFirstOptionUid = $this->selectionUidFormatter->encode( - (int)$firstAttribute->getAttributeId(), - (int)$firstOptions[1]->getValue() - ); - $secodnAttribute = $this->getSecondConfigurableAttribute(); - $secondOptions = $secodnAttribute->getOptions(); - $secondAttributeFirstOptionUid = $this->selectionUidFormatter->encode( - (int)$secodnAttribute->getAttributeId(), - (int)$secondOptions[1]->getValue() - ); - $query = <<graphQlQuery($query); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertNotNull($response['products']['items'][0]['configurable_options_selection_metadata'] - ['variant']); - $this->assertEquals( - 'simple_' . $firstOptions[1]->getValue() . '_' . $secondOptions[1]->getValue(), - $response['products']['items'][0]['configurable_options_selection_metadata'] - ['variant']['sku'] - ); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php - */ - public function testMediaGalleryForAll() - { - $query = <<graphQlQuery($query); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertEquals(14, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['media_gallery'])); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php - */ - public function testMediaGalleryWithSelection() - { - $attribute = $this->getFirstConfigurableAttribute(); - $options = $attribute->getOptions(); - $lastOptionUid = $this->selectionUidFormatter->encode( - (int)$attribute->getAttributeId(), - (int)$options[4]->getValue() - ); - $query = <<graphQlQuery($query); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertEquals(2, count($response['products']['items'][0]['configurable_options_selection_metadata'] - ['media_gallery'])); - } - - /** - * Assert option uid. - * - * @param $attributeId - * @param $expectedOptions - * @param $selectedOptions - */ - private function assertAvailableOptionUids($attributeId, $expectedOptions, $selectedOptions) - { - unset($expectedOptions[0]); - foreach ($expectedOptions as $option) { - $this->assertContains( - $this->selectionUidFormatter->encode((int)$attributeId, (int)$option->getValue()), - $selectedOptions - ); - } - } - - /** - * Get first configurable attribute. - * - * @return AttributeInterface - * @throws NoSuchEntityException - */ - private function getFirstConfigurableAttribute() - { - if (!$this->firstConfigurableAttribute) { - $attributeCode = 'test_configurable_first'; - $this->firstConfigurableAttribute = $this->attributeRepository->get('catalog_product', $attributeCode); - } - - return $this->firstConfigurableAttribute; - } - - /** - * Get second configurable attribute. - * - * @return AttributeInterface - * @throws NoSuchEntityException - */ - private function getSecondConfigurableAttribute() - { - if (!$this->secondConfigurableAttribute) { - $attributeCode = 'test_configurable_second'; - $this->secondConfigurableAttribute = $this->attributeRepository->get('catalog_product', $attributeCode); - } - - return $this->secondConfigurableAttribute; - } -} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php new file mode 100644 index 0000000000000..dc5817b7a15ff --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php @@ -0,0 +1,348 @@ +attributeRepository = Bootstrap::getObjectManager()->create(AttributeRepository::class); + $this->selectionUidFormatter = Bootstrap::getObjectManager()->create(SelectionUidFormatter::class); + $this->indexerFactory = Bootstrap::getObjectManager()->create(IndexerFactory::class); + } + + /** + * Test the first option of the first attribute selected + * + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php + */ + public function testSelectedFirstAttributeFirstOption(): void + { + $attribute = $this->getFirstConfigurableAttribute(); + $options = $attribute->getOptions(); + $sku = 'configurable_12345'; + $firstOptionUid = $this->selectionUidFormatter->encode( + (int)$attribute->getAttributeId(), + (int)$options[1]->getValue() + ); + + $this->reindexAll(); + $response = $this->graphQlQuery($this->getQuery($sku, [$firstOptionUid])); + + self::assertNotEmpty($response['products']['items']); + $product = current($response['products']['items']); + self::assertEquals('ConfigurableProduct', $product['__typename']); + self::assertEquals($sku, $product['sku']); + self::assertNotEmpty($product['configurable_product_options_selection']['configurable_options']); + self::assertNull($product['configurable_product_options_selection']['variant']); + self::assertCount(1, $product['configurable_product_options_selection']['configurable_options']); + self::assertCount(4, $product['configurable_product_options_selection']['configurable_options'][0]['values']); + + $secondAttributeOptions = $this->getSecondConfigurableAttribute()->getOptions(); + $this->assertAvailableOptionUids( + $this->getSecondConfigurableAttribute()->getAttributeId(), + $secondAttributeOptions, + $this->getOptionsUids( + $product['configurable_product_options_selection']['configurable_options'][0]['values'] + ) + ); + } + + /** + * Test selected variant + * + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php + */ + public function testSelectedVariant(): void + { + $firstAttribute = $this->getFirstConfigurableAttribute(); + $firstOptions = $firstAttribute->getOptions(); + $firstAttributeFirstOptionUid = $this->selectionUidFormatter->encode( + (int)$firstAttribute->getAttributeId(), + (int)$firstOptions[1]->getValue() + ); + $secondAttribute = $this->getSecondConfigurableAttribute(); + $secondOptions = $secondAttribute->getOptions(); + $secondAttributeFirstOptionUid = $this->selectionUidFormatter->encode( + (int)$secondAttribute->getAttributeId(), + (int)$secondOptions[1]->getValue() + ); + + $sku = 'configurable_12345'; + + $this->reindexAll(); + $response = $this->graphQlQuery( + $this->getQuery($sku, [$firstAttributeFirstOptionUid, $secondAttributeFirstOptionUid]) + ); + + self::assertNotEmpty($response['products']['items']); + $product = current($response['products']['items']); + self::assertEquals('ConfigurableProduct', $product['__typename']); + self::assertEquals($sku, $product['sku']); + self::assertEmpty($product['configurable_product_options_selection']['configurable_options']); + self::assertNotNull($product['configurable_product_options_selection']['variant']); + } + + /** + * Test without selected options + * + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php + */ + public function testWithoutSelectedOption(): void + { + $sku = 'configurable_12345'; + $this->reindexAll(); + $response = $this->graphQlQuery($this->getQuery($sku)); + + self::assertNotEmpty($response['products']['items']); + $product = current($response['products']['items']); + self::assertEquals('ConfigurableProduct', $product['__typename']); + self::assertEquals($sku, $product['sku']); + + self::assertNotEmpty($product['configurable_product_options_selection']['configurable_options']); + self::assertNull($product['configurable_product_options_selection']['variant']); + self::assertCount(2, $product['configurable_product_options_selection']['configurable_options']); + self::assertCount(4, $product['configurable_product_options_selection']['configurable_options'][0]['values']); + self::assertCount(4, $product['configurable_product_options_selection']['configurable_options'][1]['values']); + + $firstAttributeOptions = $this->getFirstConfigurableAttribute()->getOptions(); + $this->assertAvailableOptionUids( + $this->getFirstConfigurableAttribute()->getAttributeId(), + $firstAttributeOptions, + $this->getOptionsUids( + $product['configurable_product_options_selection']['configurable_options'][0]['values'] + ) + ); + + $secondAttributeOptions = $this->getSecondConfigurableAttribute()->getOptions(); + $this->assertAvailableOptionUids( + $this->getSecondConfigurableAttribute()->getAttributeId(), + $secondAttributeOptions, + $this->getOptionsUids( + $product['configurable_product_options_selection']['configurable_options'][1]['values'] + ) + ); + } + + /** + * Test with wrong selected options + * + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php + */ + public function testWithWrongSelectedOptions(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('configurableOptionValueUids values are incorrect'); + + $attribute = $this->getFirstConfigurableAttribute(); + $options = $attribute->getOptions(); + $sku = 'configurable_12345'; + $firstOptionUid = $this->selectionUidFormatter->encode( + (int)$attribute->getAttributeId(), + $options[1]->getValue() + 100 + ); + + $this->reindexAll(); + $this->graphQlQuery($this->getQuery($sku, [$firstOptionUid])); + } + + /** + * Get GraphQL query to test configurable product options selection + * + * @param string $productSku + * @param array $optionValueUids + * @param int $pageSize + * @param int $currentPage + * @return string + */ + private function getQuery( + string $productSku, + array $optionValueUids = [], + int $pageSize = 20, + int $currentPage = 1 + ): string { + if (empty($optionValueUids)) { + $configurableOptionValueUids = ''; + } else { + $configurableOptionValueUids = '(configurableOptionValueUids: ['; + foreach ($optionValueUids as $configurableOptionValueUid) { + $configurableOptionValueUids .= '"' . $configurableOptionValueUid . '",'; + } + $configurableOptionValueUids .= '])'; + } + + return <<firstConfigurableAttribute) { + $this->firstConfigurableAttribute = $this->attributeRepository->get( + 'catalog_product', + 'test_configurable_first' + ); + } + + return $this->firstConfigurableAttribute; + } + + /** + * Get second configurable attribute. + * + * @return AttributeInterface + * @throws NoSuchEntityException + */ + private function getSecondConfigurableAttribute(): AttributeInterface + { + if (!$this->secondConfigurableAttribute) { + $this->secondConfigurableAttribute = $this->attributeRepository->get( + 'catalog_product', + 'test_configurable_second' + ); + } + + return $this->secondConfigurableAttribute; + } + + /** + * Assert option uid. + * + * @param $attributeId + * @param $expectedOptions + * @param $selectedOptions + */ + private function assertAvailableOptionUids($attributeId, $expectedOptions, $selectedOptions): void + { + unset($expectedOptions[0]); + foreach ($expectedOptions as $option) { + self::assertContains( + $this->selectionUidFormatter->encode((int)$attributeId, (int)$option->getValue()), + $selectedOptions + ); + } + } + + /** + * Make fulltext catalog search reindex + * + * @return void + * @throws \Throwable + */ + private function reindexAll(): void + { + $indexLists = [ + 'catalog_category_product', + 'catalog_product_attribute', + 'cataloginventory_stock', + 'catalogsearch_fulltext', + ]; + + foreach ($indexLists as $indexerId) { + $indexer = $this->indexerFactory->create(); + $indexer->load($indexerId)->reindexAll(); + } + } + + /** + * Retrieve options UIDs + * + * @param array $options + * @return array + */ + private function getOptionsUids(array $options): array + { + $uids = []; + foreach ($options as $option) { + $uids[] = $option['uid']; + } + return $uids; + } +} From 6831e5213535c4393c9863cd121e9730d871a39f Mon Sep 17 00:00:00 2001 From: Oleksandr Melnyk Date: Tue, 12 Jan 2021 19:13:24 +0200 Subject: [PATCH 03/40] magento/magento2#31332:Shema changes implementation for configurable product option selection - added tests for media gallery --- .../ConfigurableOptionsSelectionTest.php | 36 +++++++++++ ...oducts_with_two_attributes_combination.php | 63 ++++++++++++++----- 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php index dc5817b7a15ff..7ea02a0fa1a45 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php @@ -12,6 +12,7 @@ use Magento\Eav\Api\Data\AttributeInterface; use Magento\Eav\Model\AttributeRepository; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\GraphQl\Query\Uid; use Magento\Indexer\Model\IndexerFactory; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -36,6 +37,11 @@ class ConfigurableOptionsSelectionTest extends GraphQlAbstract */ private $indexerFactory; + /** + * @var Uid + */ + private $idEncoder; + private $firstConfigurableAttribute; private $secondConfigurableAttribute; @@ -48,6 +54,7 @@ protected function setUp(): void $this->attributeRepository = Bootstrap::getObjectManager()->create(AttributeRepository::class); $this->selectionUidFormatter = Bootstrap::getObjectManager()->create(SelectionUidFormatter::class); $this->indexerFactory = Bootstrap::getObjectManager()->create(IndexerFactory::class); + $this->idEncoder = Bootstrap::getObjectManager()->create(Uid::class); } /** @@ -85,6 +92,8 @@ public function testSelectedFirstAttributeFirstOption(): void $product['configurable_product_options_selection']['configurable_options'][0]['values'] ) ); + + $this->assertMediaGallery($product); } /** @@ -120,6 +129,18 @@ public function testSelectedVariant(): void self::assertEquals($sku, $product['sku']); self::assertEmpty($product['configurable_product_options_selection']['configurable_options']); self::assertNotNull($product['configurable_product_options_selection']['variant']); + + $variantId = $this->idEncoder->decode($product['configurable_product_options_selection']['variant']['uid']); + self::assertIsNumeric($variantId); + self::assertIsString($product['configurable_product_options_selection']['variant']['sku']); + $urlKey = 'configurable-option-first-option-1-second-option-1'; + self::assertEquals($urlKey, $product['configurable_product_options_selection']['variant']['url_key']); + self::assertMatchesRegularExpression( + "/{$urlKey}/", + $product['configurable_product_options_selection']['variant']['url_path'] + ); + + $this->assertMediaGallery($product); } /** @@ -161,6 +182,8 @@ public function testWithoutSelectedOption(): void $product['configurable_product_options_selection']['configurable_options'][1]['values'] ) ); + + $this->assertMediaGallery($product); } /** @@ -345,4 +368,17 @@ private function getOptionsUids(array $options): array } return $uids; } + + /** + * Assert media gallery fields + * + * @param array $product + */ + private function assertMediaGallery(array $product): void + { + self::assertNotEmpty($product['configurable_product_options_selection']['media_gallery']); + $image = current($product['configurable_product_options_selection']['media_gallery']); + self::assertIsString($image['url']); + self::assertEquals(false, $image['disabled']); + } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php index 24e6010275bac..f26e39ca8e2a2 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_products_with_two_attributes_combination.php @@ -3,10 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Indexer\Product\Price\Processor as PriceIndexerProcessor; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Media\Config; use Magento\Catalog\Model\Product\Type; use Magento\Catalog\Model\Product\Visibility; use Magento\Catalog\Setup\CategorySetup; @@ -15,8 +17,11 @@ use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Eav\Api\Data\AttributeOptionInterface; use Magento\Framework\Api\Data\ImageContentInterface; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Workaround\Override\Fixture\Resolver; +use Magento\Framework\App\Filesystem\DirectoryList; Resolver::getInstance()->requireDataFixture( 'Magento/ConfigurableProduct/_files/configurable_attribute_first.php' @@ -25,18 +30,31 @@ 'Magento/ConfigurableProduct/_files/configurable_attribute_second.php' ); +$objectManager = Bootstrap::getObjectManager(); + /** @var ProductRepositoryInterface $productRepository */ -$productRepository = Bootstrap::getObjectManager() - ->get(ProductRepositoryInterface::class); +$productRepository = $objectManager->get(ProductRepositoryInterface::class); /** @var $installer CategorySetup */ -$installer = Bootstrap::getObjectManager()->create(CategorySetup::class); +$installer = $objectManager->create(CategorySetup::class); /** @var \Magento\Eav\Model\Config $eavConfig */ -$eavConfig = Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class); +$eavConfig = $objectManager->get(\Magento\Eav\Model\Config::class); $firstAttribute = $eavConfig->getAttribute(Product::ENTITY, 'test_configurable_first'); $secondAttribute = $eavConfig->getAttribute(Product::ENTITY, 'test_configurable_second'); +/** @var Config $config */ +$config = $objectManager->get(Config::class); + +/** @var Filesystem $filesystem */ +$filesystem = $objectManager->get(Filesystem::class); + +/** @var WriteInterface $mediaDirectory */ +$mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); +$mediaPath = $mediaDirectory->getAbsolutePath(); +$baseTmpMediaPath = $config->getBaseTmpMediaPath(); +$mediaDirectory->create($baseTmpMediaPath); + /* Create simple products per each option value*/ /** @var AttributeOptionInterface[] $firstAttributeOptions */ $firstAttributeOptions = $firstAttribute->getOptions(); @@ -48,6 +66,8 @@ $firstAttributeValues = []; $secondAttributeValues = []; $testImagePath = __DIR__ . '/magento_image.jpg'; +$mediaImage = $mediaPath . '/' . $baseTmpMediaPath . '/magento_image.jpg'; +copy($testImagePath, $mediaImage); array_shift($firstAttributeOptions); array_shift($secondAttributeOptions); @@ -65,7 +85,10 @@ $qty = 100; $isInStock = 1; } - $product = Bootstrap::getObjectManager()->create(Product::class); + + $image = '/m/a/magento_image.jpg'; + + $product = $objectManager->create(Product::class); $product->setTypeId(Type::TYPE_SIMPLE) ->setAttributeSetId($attributeSetId) ->setWebsiteIds([1]) @@ -79,15 +102,15 @@ ->setStockData( ['use_config_manage_stock' => 1, 'qty' => $qty, 'is_qty_decimal' => 0, 'is_in_stock' => $isInStock] ) - ->setImage('/m/a/magento_image.jpg') - ->setSmallImage('/m/a/magento_image.jpg') - ->setThumbnail('/m/a/magento_image.jpg') + ->setImage($image) + ->setSmallImage($image) + ->setThumbnail($image) ->setData( 'media_gallery', [ 'images' => [ [ - 'file' => '/m/a/magento_image.jpg', + 'file' => $image, 'position' => 1, 'label' => 'Image Alt Text', 'disabled' => 0, @@ -113,11 +136,12 @@ foreach ($customAttributes as $attributeCode => $attributeValue) { $product->setCustomAttributes($customAttributes); } + $product = $productRepository->save($product); $associatedProductIds[] = $product->getId(); - /** @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */ - $stockItem = Bootstrap::getObjectManager()->create(Item::class); + /** @var Item $stockItem */ + $stockItem = $objectManager->create(Item::class); $stockItem->load($product->getId(), 'product_id'); if (!$stockItem->getProductId()) { @@ -135,17 +159,16 @@ 'value_index' => $secondAttributeOption->getValue(), ]; } - } -$indexerProcessor = Bootstrap::getObjectManager()->get(PriceIndexerProcessor::class); +$indexerProcessor = $objectManager->get(PriceIndexerProcessor::class); $indexerProcessor->reindexList($associatedProductIds, true); /** @var $product Product */ -$product = Bootstrap::getObjectManager()->create(Product::class); +$product = $objectManager->create(Product::class); /** @var Factory $optionsFactory */ -$optionsFactory = Bootstrap::getObjectManager()->create(Factory::class); +$optionsFactory = $objectManager->create(Factory::class); $configurableAttributesData = [ [ @@ -180,9 +203,15 @@ ->setSku('configurable_12345') ->setVisibility(Visibility::VISIBILITY_BOTH) ->setStatus(Status::STATUS_ENABLED) - ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->addImageToMediaGallery( + $mediaImage, + ['image', 'small_image', 'thumbnail'], + false, + false + ); $productRepository->cleanCache(); $product = $productRepository->save($product); -$indexerProcessor = Bootstrap::getObjectManager()->get(PriceIndexerProcessor::class); +$indexerProcessor = $objectManager->get(PriceIndexerProcessor::class); $indexerProcessor->reindexRow($product->getId(), true); From b339166faec5fd9832ecf3e05b6d2cbebe343458 Mon Sep 17 00:00:00 2001 From: Oleksandr Melnyk Date: Wed, 13 Jan 2021 12:12:38 +0200 Subject: [PATCH 04/40] magento/magento2#31332:Schema changes implementation for configurable option selection - fixed webapi tests --- .../Model/Options/SelectionUidFormatter.php | 6 +- ...gurableProductToCartSingleMutationTest.php | 86 +++++++++++-------- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php index 7bcf08a9b9509..8c82c9414763f 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/SelectionUidFormatter.php @@ -46,11 +46,7 @@ public function __construct(Uid $idEncoder) */ public function encode(int $attributeId, int $indexId): string { - return $this->idEncoder->encode(implode(self::UID_SEPARATOR, [ - self::UID_PREFIX, - $attributeId, - $indexId - ])); + return $this->idEncoder->encode(implode(self::UID_SEPARATOR, [self::UID_PREFIX, $attributeId, $indexId])); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartSingleMutationTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartSingleMutationTest.php index 5a08692d5dcdd..b26e5b4139d0f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartSingleMutationTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartSingleMutationTest.php @@ -3,18 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + declare(strict_types=1); namespace Magento\GraphQl\ConfigurableProduct; use Exception; +use Magento\CatalogInventory\Model\Configuration; use Magento\Config\Model\ResourceModel\Config; +use Magento\ConfigurableProductGraphQl\Model\Options\SelectionUidFormatter; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -use Magento\CatalogInventory\Model\Configuration; /** * Add configurable product to cart testcases @@ -41,6 +43,11 @@ class AddConfigurableProductToCartSingleMutationTest extends GraphQlAbstract */ private $reinitConfig; + /** + * @var SelectionUidFormatter + */ + private $selectionUidFormatter; + /** * @inheritdoc */ @@ -51,13 +58,14 @@ protected function setUp(): void $this->resourceConfig = $objectManager->get(Config::class); $this->scopeConfig = $objectManager->get(ScopeConfigInterface::class); $this->reinitConfig = $objectManager->get(ReinitableConfigInterface::class); + $this->selectionUidFormatter = $objectManager->get(SelectionUidFormatter::class); } /** * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddConfigurableProductToCart() + public function testAddConfigurableProductToCart(): void { $product = $this->getConfigurableProductInfo(); $quantity = 2; @@ -77,7 +85,8 @@ public function testAddConfigurableProductToCart() ); $response = $this->graphQlMutation($query); - $expectedProductOptionsValueUid = $this->generateConfigurableSelectionUID($attributeId, $valueIndex); + + $expectedProductOptionsValueUid = $this->selectionUidFormatter->encode($attributeId, $valueIndex); $expectedProductOptionsUid = base64_encode("configurable/$productRowId/$attributeId"); $cartItem = current($response['addProductsToCart']['cart']['items']); self::assertEquals($quantity, $cartItem['quantity']); @@ -94,35 +103,11 @@ public function testAddConfigurableProductToCart() self::assertArrayHasKey('value_label', $option); } - /** - * Generates UID configurable product - * - * @param int $attributeId - * @param int $valueIndex - * @return string - */ - private function generateConfigurableSelectionUID(int $attributeId, int $valueIndex): string - { - return base64_encode("configurable/$attributeId/$valueIndex"); - } - - /** - * Generates UID for super configurable product super attributes - * - * @param int $attributeId - * @param int $valueIndex - * @return string - */ - private function generateSuperAttributesUIDQuery(int $attributeId, int $valueIndex): string - { - return 'selected_options: ["' . $this->generateConfigurableSelectionUID($attributeId, $valueIndex) . '"]'; - } - /** * @magentoApiDataFixture Magento/Catalog/_files/configurable_products_with_custom_attribute_layered_navigation.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddConfigurableProductWithWrongSuperAttributes() + public function testAddConfigurableProductWithWrongSuperAttributes(): void { $product = $this->getConfigurableProductInfo(); $quantity = 2; @@ -150,7 +135,7 @@ public function testAddConfigurableProductWithWrongSuperAttributes() * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddProductIfQuantityIsNotAvailable() + public function testAddProductIfQuantityIsNotAvailable(): void { $product = $this->getConfigurableProductInfo(); $parentSku = $product['sku']; @@ -179,7 +164,7 @@ public function testAddProductIfQuantityIsNotAvailable() * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddNonExistentConfigurableProductParentToCart() + public function testAddNonExistentConfigurableProductParentToCart(): void { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $parentSku = 'configurable_no_exist'; @@ -203,7 +188,7 @@ public function testAddNonExistentConfigurableProductParentToCart() * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_zero_qty_first_child.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testOutOfStockVariationToCart() + public function testOutOfStockVariationToCart(): void { $showOutOfStock = $this->scopeConfig->getValue(Configuration::XML_PATH_SHOW_OUT_OF_STOCK); @@ -215,7 +200,7 @@ public function testOutOfStockVariationToCart() $attributeId = (int) $product['configurable_options'][0]['attribute_id']; $valueIndex = $product['configurable_options'][0]['values'][0]['value_index']; // Asserting that the first value is the right option we want to add to cart - $this->assertEquals( + self::assertEquals( $product['configurable_options'][0]['values'][0]['label'], 'Option 1' ); @@ -237,7 +222,7 @@ public function testOutOfStockVariationToCart() 'There are no source items with the in stock status', 'This product is out of stock.' ]; - $this->assertContains( + self::assertContains( $response['addProductsToCart']['user_errors'][0]['message'], $expectedErrorMessages ); @@ -312,6 +297,18 @@ private function getConfigurableProductInfo(): array return current($searchResponse['products']['items']); } + /** + * Generates UID for super configurable product super attributes + * + * @param int $attributeId + * @param int $valueIndex + * @return string + */ + private function generateSuperAttributesUIDQuery(int $attributeId, int $valueIndex): string + { + return 'selected_options: ["' . $this->selectionUidFormatter->encode($attributeId, $valueIndex) . '"]'; + } + /** * Returns GraphQl query for fetching configurable product information * @@ -349,15 +346,28 @@ private function getFetchProductQuery(string $term): string value_index } } - configurable_options_selection_metadata { - options_available_for_selection { + configurable_product_options_selection { + configurable_options { + uid attribute_code - option_value_uids + label + values { + uid + is_available + is_use_default + label + } } variant { uid - name - attribute_set_id + sku + url_key + url_path + } + media_gallery { + url + label + disabled } } } From 1bdd266ef4b3a4b46a93107dc6503b25f2e5b495 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin Date: Thu, 25 Feb 2021 11:39:58 +0200 Subject: [PATCH 05/40] MC-40873: Product is shown as Out of Stock on CMS page when Category Permissions are enabled --- .../templates/product/widget/new/content/new_grid.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml index 5108c488aec19..66683ef328e08 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml @@ -89,7 +89,7 @@ if ($exist = ($block->getProductCollection() && $block->getProductCollection()-> - getIsSalable()) :?> + isAvailable()) :?>
escapeHtml(__('In stock')) ?>
From 7aa440274777d73e52bd9718e994c424346ed515 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Fri, 26 Feb 2021 09:44:38 -0600 Subject: [PATCH 06/40] PWA-1326: Implement the schema changes for Configurable Options Selection - remove circular dependency --- app/code/Magento/ConfigurableProductGraphQl/composer.json | 1 - app/code/Magento/ConfigurableProductGraphQl/etc/module.xml | 1 - app/code/Magento/SwatchesGraphQl/composer.json | 3 ++- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/composer.json b/app/code/Magento/ConfigurableProductGraphQl/composer.json index 72ecdbc3a375f..a6e1d1c822435 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/composer.json +++ b/app/code/Magento/ConfigurableProductGraphQl/composer.json @@ -11,7 +11,6 @@ "magento/module-quote": "*", "magento/module-quote-graph-ql": "*", "magento/module-catalog-inventory": "*", - "magento/module-swatches-graph-ql": "*", "magento/framework": "*" }, "license": [ diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml b/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml index e6345ac188631..3aa1658c9388d 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/module.xml @@ -14,7 +14,6 @@ - diff --git a/app/code/Magento/SwatchesGraphQl/composer.json b/app/code/Magento/SwatchesGraphQl/composer.json index 1b98b4044a2ff..8b6651f89f3b7 100644 --- a/app/code/Magento/SwatchesGraphQl/composer.json +++ b/app/code/Magento/SwatchesGraphQl/composer.json @@ -7,7 +7,8 @@ "magento/framework": "*", "magento/module-swatches": "*", "magento/module-catalog": "*", - "magento/module-catalog-graph-ql": "*" + "magento/module-catalog-graph-ql": "*", + "magento/module-configurable-product-graph-ql": "*" }, "license": [ "OSL-3.0", From f7903ab4de011ed44572d38f30ad66943dc05dd4 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Fri, 26 Feb 2021 18:16:03 -0600 Subject: [PATCH 07/40] PWA-1326: Implement the schema changes for Configurable Options Selection - renaming metadata back to original name for comparison purposes --- .../{OptionsSelection.php => OptionsSelectionMetadata.php} | 3 ++- .../Magento/ConfigurableProductGraphQl/etc/schema.graphqls | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/{OptionsSelection.php => OptionsSelectionMetadata.php} (97%) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php similarity index 97% rename from app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php rename to app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php index 6d1e4cbf5bb00..60369a5645868 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelection.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\ConfigurableProductGraphQl\Model\Resolver; @@ -19,7 +20,7 @@ /** * Resolver for options selection */ -class OptionsSelection implements ResolverInterface +class OptionsSelectionMetadata implements ResolverInterface { /** * @var Metadata diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index 9949ed1f8c417..d9ba786c84354 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -7,7 +7,7 @@ type Mutation { type ConfigurableProduct implements ProductInterface, PhysicalProductInterface, CustomizableProductInterface @doc(description: "ConfigurableProduct defines basic features of a configurable product and its simple product variants") { variants: [ConfigurableVariant] @doc(description: "An array of variants of products") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\ConfigurableVariant") configurable_options: [ConfigurableProductOptions] @doc(description: "An array of linked simple product items") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\Options") - configurable_product_options_selection(configurableOptionValueUids: [ID!]): ConfigurableProductOptionsSelection @doc(description: "Specified configurable product options selection") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\OptionsSelection") + configurable_product_options_selection(configurableOptionValueUids: [ID!]): ConfigurableProductOptionsSelection @doc(description: "Specified configurable product options selection") @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\OptionsSelectionMetadata") } type ConfigurableVariant @doc(description: "An array containing all the simple product variants of a configurable product") { From adacf15197d43c8278427c91980302a3f6f6956b Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin Date: Mon, 1 Mar 2021 15:02:50 +0200 Subject: [PATCH 08/40] MC-40873: Product is shown as Out of Stock on CMS page when Category Permissions are enabled --- .../Catalog/view/frontend/templates/product/compare/list.phtml | 2 +- .../Catalog/view/frontend/templates/product/list/items.phtml | 2 +- .../Catalog/view/frontend/templates/product/listing.phtml | 2 +- .../templates/product/widget/new/column/new_default_list.phtml | 2 +- .../templates/product/widget/new/content/new_list.phtml | 2 +- .../view/frontend/templates/product/widget/content/grid.phtml | 2 +- .../view/frontend/templates/catalog/product/type.phtml | 2 +- .../view/frontend/templates/product/widget/viewed/item.phtml | 2 +- .../widget/compared/column/compared_default_list.phtml | 2 +- .../templates/widget/compared/content/compared_grid.phtml | 2 +- .../templates/widget/compared/content/compared_list.phtml | 2 +- .../templates/widget/viewed/column/viewed_default_list.phtml | 2 +- .../frontend/templates/widget/viewed/content/viewed_grid.phtml | 2 +- .../frontend/templates/widget/viewed/content/viewed_list.phtml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml index 0bea3ca03dee8..bd37ad17f23ae 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml @@ -78,7 +78,7 @@ - getIsSalable()) :?> + isAvailable()) :?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml index e426b940deab7..6fd619de7fd6c 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml @@ -287,7 +287,7 @@ $_item = null; - getIsSalable()):?> + isAvailable()):?>
escapeHtml(__('In stock')) ?>
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml index 6cebd51284f48..49dd702a6e39c 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml @@ -63,7 +63,7 @@ $_helper = $this->helper(Magento\Catalog\Helper\Output::class); . ' data-mage-init=\'{ "redirectUrl": { "event": "click", url: "' . $block->escapeUrl($block->getAddToCartUrl($_product)) . '"} }\'>' . '' . $block->escapeHtml(__('Add to Cart')) . ''; } else { - $info['button'] = $_product->getIsSalable() ? '
' . $block->escapeHtml(__('In stock')) . '
' : + $info['button'] = $_product->isAvailable() ? '
' . $block->escapeHtml(__('In stock')) . '
' : '
' . $block->escapeHtml(__('Out of stock')) . '
'; } diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/column/new_default_list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/column/new_default_list.phtml index 53a0682311b1f..fce91564c96a2 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/column/new_default_list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/column/new_default_list.phtml @@ -52,7 +52,7 @@ - getIsSalable()) :?> + isAvailable()) :?>
escapeHtml(__('In stock')) ?>
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml index 378cd49493a6e..ceb32e78c7e44 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml @@ -88,7 +88,7 @@ if ($exist = ($block->getProductCollection() && $block->getProductCollection()-> - getIsSalable()) :?> + isAvailable()) :?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml b/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml index 9637815c90eef..000f3ffd36934 100644 --- a/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml +++ b/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml @@ -77,7 +77,7 @@ use Magento\Framework\App\Action\Action; - getIsSalable()): ?> + isAvailable()): ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/type.phtml b/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/type.phtml index ba6d9e0abec71..e5397e758d63f 100644 --- a/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/type.phtml +++ b/app/code/Magento/Downloadable/view/frontend/templates/catalog/product/type.phtml @@ -12,7 +12,7 @@ ?> getProduct() ?> -getIsSalable()) : ?> +isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml b/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml index 562c9a2b63a99..da11582a16133 100644 --- a/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml @@ -60,7 +60,7 @@ $rating = 'short'; - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml index a54259280e381..a9d5718449cd5 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/column/compared_default_list.phtml @@ -78,7 +78,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml index ad6b33820c752..1222490065185 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml @@ -83,7 +83,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml index ba7a50eef6485..6f7b4f4f66f27 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml @@ -84,7 +84,7 @@ if ($exist = $block->getRecentlyComparedProducts()) { - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml index 16fc2b070b95c..3e5cd15bbc62b 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/column/viewed_default_list.phtml @@ -81,7 +81,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml index 567c3ebc57f9b..c2f98e72909d6 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml @@ -86,7 +86,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml index 9a8bb9c3b734f..32cf0bc69d1e5 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml @@ -88,7 +88,7 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr - getIsSalable()) : ?> + isAvailable()) : ?>
escapeHtml(__('In stock')) ?>
escapeHtml(__('Out of stock')) ?>
From 07592df80161067eb3ee0e62503685bf11b4f640 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Mon, 1 Mar 2021 10:32:53 -0600 Subject: [PATCH 09/40] PWA-1326: Implement the schema changes for Configurable Options Selection - combining schema with variant attribute details --- .../Products/DataProvider/ProductSearch.php | 10 --- .../Options/ConfigurableOptionsMetadata.php | 86 +++++++++++++++++++ .../Model/Options/Metadata.php | 2 +- .../Resolver/OptionsSelectionMetadata.php | 30 +++++-- .../Model/Resolver/SelectionMediaGallery.php | 4 +- 5 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php index bcf0aa15b9e63..13bd29e83d87f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php @@ -18,8 +18,6 @@ use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Api\SearchResultsInterface; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\GraphQl\Model\Query\ContextInterface; /** @@ -89,7 +87,6 @@ public function __construct( * @param array $attributes * @param ContextInterface|null $context * @return SearchResultsInterface - * @throws GraphQlNoSuchEntityException */ public function getList( SearchCriteriaInterface $searchCriteria, @@ -110,13 +107,6 @@ public function getList( )->apply(); $this->collectionPreProcessor->process($collection, $searchCriteriaForCollection, $attributes, $context); - - try { - $collection->addMediaGalleryData(); - } catch (LocalizedException $e) { - throw new GraphQlNoSuchEntityException(__('Cannot load media gallery')); - } - $collection->load(); $this->collectionPostProcessor->process($collection, $attributes); diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php new file mode 100644 index 0000000000000..5e0c5535c564c --- /dev/null +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php @@ -0,0 +1,86 @@ +configurableProductHelper = $configurableProductHelper; + $this->configurableOptionsFormatter = $configurableOptionsFormatter; + } + + /** + * Load available selections from configurable options and variant. + * + * @param ProductInterface $product + * @param array $options + * @param array $selectedOptions + * @return array + */ + public function getAvailableSelections(ProductInterface $product, array $options, array $selectedOptions): array + { + $attributes = $this->getAttributes($product); + $availableSelections = []; + + foreach ($options as $attributeId => $option) { + if ($attributeId === 'index' || isset($selectedOptions[$attributeId])) { + continue; + } + + $availableSelections[] = $this->configurableOptionsFormatter->format( + $attributes[$attributeId], + $options[$attributeId] ?? [] + ); + } + + return $availableSelections; + } + + /** + * Retrieve configurable attributes for the product + * + * @param ProductInterface $product + * @return Attribute[] + */ + private function getAttributes(ProductInterface $product): array + { + $allowedAttributes = $this->configurableProductHelper->getAllowAttributes($product); + $attributes = []; + foreach ($allowedAttributes as $attribute) { + $attributes[$attribute->getAttributeId()] = $attribute; + } + + return $attributes; + } +} diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php index 5e0c5535c564c..ce81e970bcd58 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php @@ -16,7 +16,7 @@ /** * Retrieve metadata for configurable option selection. */ -class Metadata +class ConfigurableOptionsMetadata { /** * @var Data diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php index 60369a5645868..556aab7e39f7d 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/OptionsSelectionMetadata.php @@ -9,6 +9,7 @@ use Magento\ConfigurableProduct\Helper\Data; use Magento\ConfigurableProductGraphQl\Model\Formatter\Variant as VariantFormatter; +use Magento\ConfigurableProductGraphQl\Model\Options\ConfigurableOptionsMetadata; use Magento\ConfigurableProductGraphQl\Model\Options\DataProvider\Variant; use Magento\ConfigurableProductGraphQl\Model\Options\Metadata; use Magento\ConfigurableProductGraphQl\Model\Options\SelectionUidFormatter; @@ -27,6 +28,11 @@ class OptionsSelectionMetadata implements ResolverInterface */ private $configurableSelectionMetadata; + /** + * @var ConfigurableOptionsMetadata + */ + private $configurableOptionsMetadata; + /** * @var SelectionUidFormatter */ @@ -49,6 +55,7 @@ class OptionsSelectionMetadata implements ResolverInterface /** * @param Metadata $configurableSelectionMetadata + * @param ConfigurableOptionsMetadata $configurableOptionsMetadata * @param SelectionUidFormatter $selectionUidFormatter * @param Variant $variant * @param VariantFormatter $variantFormatter @@ -56,12 +63,14 @@ class OptionsSelectionMetadata implements ResolverInterface */ public function __construct( Metadata $configurableSelectionMetadata, + ConfigurableOptionsMetadata $configurableOptionsMetadata, SelectionUidFormatter $selectionUidFormatter, Variant $variant, VariantFormatter $variantFormatter, Data $configurableProductHelper ) { $this->configurableSelectionMetadata = $configurableSelectionMetadata; + $this->configurableOptionsMetadata = $configurableOptionsMetadata; $this->selectionUidFormatter = $selectionUidFormatter; $this->variant = $variant; $this->variantFormatter = $variantFormatter; @@ -85,14 +94,23 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $variants = $this->variant->getSalableVariantsByParent($product); $options = $this->configurableProductHelper->getOptions($product, $variants); + $configurableOptions = $this->configurableOptionsMetadata->getAvailableSelections( + $product, + $options, + $selectedOptions + ); + + $optionsAvailableForSelection = $this->configurableSelectionMetadata->getAvailableSelections( + $product, + $args['configurableOptionValueUids'] ?? [] + ); + return [ - 'configurable_options' => $this->configurableSelectionMetadata->getAvailableSelections( - $product, - $options, - $selectedOptions - ), + 'configurable_options' => $configurableOptions, 'variant' => $this->variantFormatter->format($options, $selectedOptions, $variants), - 'model' => $product + 'model' => $product, + 'options_available_for_selection' => $optionsAvailableForSelection['options_available_for_selection'], + 'availableSelectionProducts' => $optionsAvailableForSelection['availableSelectionProducts'] ]; } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php index 4aa322e66df60..972e4a9fd629a 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/SelectionMediaGallery.php @@ -21,11 +21,11 @@ class SelectionMediaGallery implements ResolverInterface */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - if (!isset($value['product']) || !$value['product']) { + if (!isset($value['model']) || !$value['model']) { return null; } - $product = $value['product']; + $product = $value['model']; $availableSelectionProducts = $value['availableSelectionProducts']; $mediaGalleryEntries = []; $usedProducts = $product->getTypeInstance()->getUsedProducts($product, null); From c9a6164a024a3f4b91790b30a1fb7bc60508619e Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Mon, 1 Mar 2021 10:38:56 -0600 Subject: [PATCH 10/40] PWA-1326: Implement the schema changes for Configurable Options Selection - combining schema with variant attribute details --- .../Options/ConfigurableOptionsMetadata.php | 2 +- .../Model/Options/Metadata.php | 147 ++++++++++++++---- .../ConfigurableOptionsSelectionTest.php | 5 - 3 files changed, 118 insertions(+), 36 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php index 5e0c5535c564c..ce81e970bcd58 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/ConfigurableOptionsMetadata.php @@ -16,7 +16,7 @@ /** * Retrieve metadata for configurable option selection. */ -class Metadata +class ConfigurableOptionsMetadata { /** * @var Data diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php index ce81e970bcd58..9fa6e4f23fa56 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/Metadata.php @@ -3,20 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - declare(strict_types=1); namespace Magento\ConfigurableProductGraphQl\Model\Options; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\ConfigurableProduct\Helper\Data; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute; -use Magento\ConfigurableProductGraphQl\Model\Formatter\Option; +use Magento\ConfigurableProductGraphQl\Model\Options\DataProvider\Variant; +use Magento\Framework\Exception\NoSuchEntityException; /** * Retrieve metadata for configurable option selection. */ -class ConfigurableOptionsMetadata +class Metadata { /** * @var Data @@ -24,63 +24,150 @@ class ConfigurableOptionsMetadata private $configurableProductHelper; /** - * @var Option + * @var SelectionUidFormatter + */ + private $selectionUidFormatter; + + /** + * @var ProductRepositoryInterface */ - private $configurableOptionsFormatter; + private $productRepository; + + /** + * @var Variant + */ + private $variant; /** * @param Data $configurableProductHelper - * @param Option $configurableOptionsFormatter + * @param SelectionUidFormatter $selectionUidFormatter + * @param ProductRepositoryInterface $productRepository + * @param Variant $variant */ public function __construct( Data $configurableProductHelper, - Option $configurableOptionsFormatter + SelectionUidFormatter $selectionUidFormatter, + ProductRepositoryInterface $productRepository, + Variant $variant ) { $this->configurableProductHelper = $configurableProductHelper; - $this->configurableOptionsFormatter = $configurableOptionsFormatter; + $this->selectionUidFormatter = $selectionUidFormatter; + $this->productRepository = $productRepository; + $this->variant = $variant; } /** - * Load available selections from configurable options and variant. + * Load available selections from configurable options. * * @param ProductInterface $product - * @param array $options - * @param array $selectedOptions + * @param array $selectedOptionsUid * @return array + * @throws NoSuchEntityException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function getAvailableSelections(ProductInterface $product, array $options, array $selectedOptions): array - { - $attributes = $this->getAttributes($product); - $availableSelections = []; + public function getAvailableSelections( + ProductInterface $product, + array $selectedOptionsUid + ): array { + $options = $this->configurableProductHelper->getOptions($product, $this->getAllowProducts($product)); + $selectedOptions = $this->selectionUidFormatter->extract($selectedOptionsUid); + $attributeCodes = $this->getAttributeCodes($product); + $availableSelections = $availableProducts = $variantData = []; - foreach ($options as $attributeId => $option) { - if ($attributeId === 'index' || isset($selectedOptions[$attributeId])) { - continue; + if (isset($options['index']) && $options['index']) { + foreach ($options['index'] as $productId => $productOptions) { + if (!empty($selectedOptions) && !$this->hasProductRequiredOptions($selectedOptions, $productOptions)) { + continue; + } + + $availableProducts[] = $productId; + foreach ($productOptions as $attributeId => $optionIndex) { + $uid = $this->selectionUidFormatter->encode($attributeId, (int)$optionIndex); + + if (isset($availableSelections[$attributeId]['option_value_uids']) + && in_array($uid, $availableSelections[$attributeId]['option_value_uids']) + ) { + continue; + } + $availableSelections[$attributeId]['option_value_uids'][] = $uid; + $availableSelections[$attributeId]['attribute_code'] = $attributeCodes[$attributeId]; + } + + if ($this->hasSelectionProduct($selectedOptions, $productOptions)) { + $variantProduct = $this->productRepository->getById($productId); + $variantData = $variantProduct->getData(); + $variantData['model'] = $variantProduct; + } } + } + + return [ + 'options_available_for_selection' => $availableSelections, + 'variant' => $variantData, + 'availableSelectionProducts' => array_unique($availableProducts), + 'product' => $product + ]; + } + + /** + * Get allowed products. + * + * @param ProductInterface $product + * @return ProductInterface[] + */ + public function getAllowProducts(ProductInterface $product): array + { + return $this->variant->getSalableVariantsByParent($product) ?? []; + } - $availableSelections[] = $this->configurableOptionsFormatter->format( - $attributes[$attributeId], - $options[$attributeId] ?? [] - ); + /** + * Check if a product has the selected options. + * + * @param array $requiredOptions + * @param array $productOptions + * @return bool + */ + private function hasProductRequiredOptions($requiredOptions, $productOptions): bool + { + $result = true; + foreach ($requiredOptions as $attributeId => $optionIndex) { + if (!isset($productOptions[$attributeId]) || !$productOptions[$attributeId] + || $optionIndex != $productOptions[$attributeId] + ) { + $result = false; + break; + } } - return $availableSelections; + return $result; + } + + /** + * Check if selected options match a product. + * + * @param array $requiredOptions + * @param array $productOptions + * @return bool + */ + private function hasSelectionProduct($requiredOptions, $productOptions): bool + { + return $this->hasProductRequiredOptions($productOptions, $requiredOptions); } /** - * Retrieve configurable attributes for the product + * Retrieve attribute codes * * @param ProductInterface $product - * @return Attribute[] + * @return string[] */ - private function getAttributes(ProductInterface $product): array + private function getAttributeCodes(ProductInterface $product): array { $allowedAttributes = $this->configurableProductHelper->getAllowAttributes($product); - $attributes = []; + $attributeCodes = []; foreach ($allowedAttributes as $attribute) { - $attributes[$attribute->getAttributeId()] = $attribute; + $attributeCodes[$attribute->getAttributeId()] = $attribute->getProductAttribute()->getAttributeCode(); } - return $attributes; + return $attributeCodes; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php index 7ea02a0fa1a45..ac252acfcaa2b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/ConfigurableOptionsSelectionTest.php @@ -135,10 +135,6 @@ public function testSelectedVariant(): void self::assertIsString($product['configurable_product_options_selection']['variant']['sku']); $urlKey = 'configurable-option-first-option-1-second-option-1'; self::assertEquals($urlKey, $product['configurable_product_options_selection']['variant']['url_key']); - self::assertMatchesRegularExpression( - "/{$urlKey}/", - $product['configurable_product_options_selection']['variant']['url_path'] - ); $this->assertMediaGallery($product); } @@ -264,7 +260,6 @@ private function getQuery( uid sku url_key - url_path } media_gallery { url From f370a8e02166bec7c81fd115bef5020b54ac6df1 Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Tue, 2 Mar 2021 15:25:18 +0200 Subject: [PATCH 11/40] MC-40122: Double spaces not displaying for SKU in product grid --- .../Catalog/Test/Mftf/Data/ProductData.xml | 4 ++ .../AdminShowDoubleSpacesInProductGrid.xml | 52 +++++++++++++++++++ .../ui_component/product_listing.xml | 4 +- .../web/template/grid/cells/preserved.html | 7 +++ .../web/css/source/module/_data-grid.less | 4 ++ 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminShowDoubleSpacesInProductGrid.xml create mode 100644 app/code/Magento/Catalog/view/adminhtml/web/template/grid/cells/preserved.html diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 5375459122e69..f7622140c97cd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -39,6 +39,10 @@ TestFooBar foobar + + Simple Product Double Space + simple-product double-space + Pursuit Lumaflex&trade; Tone Band x&trade; diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminShowDoubleSpacesInProductGrid.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminShowDoubleSpacesInProductGrid.xml new file mode 100644 index 0000000000000..c3e939b4155c8 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminShowDoubleSpacesInProductGrid.xml @@ -0,0 +1,52 @@ + + + + + + + + + + <description value="Admin should be able to see double spaces in the Name and Sku fields in the product grid"/> + <testCaseId value="MC-40725"/> + <useCaseId value="MC-40122"/> + <severity value="AVERAGE"/> + <group value="Catalog"/> + </annotations> + + <before> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiSimpleProductWithDoubleSpaces" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <magentoCLI command="cron:run --group=index" stepKey="cronRun"/> + <magentoCLI command="cron:run --group=index" stepKey="cronRunSecondTime"/> + </before> + + <after> + <actionGroup ref="AdminDeleteAllProductsFromGridActionGroup" stepKey="deleteProduct"/> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminOpenCatalogProductPageActionGroup" stepKey="goToProductCatalogPage"/> + <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="searchForProduct"> + <argument name="product" value="$createProduct$"/> + </actionGroup> + <actionGroup ref="AssertAdminProductGridCellActionGroup" stepKey="assertProductName"> + <argument name="column" value="Name"/> + <argument name="value" value="$createProduct.name$"/> + </actionGroup> + <actionGroup ref="AssertAdminProductGridCellActionGroup" stepKey="assertProductSku"> + <argument name="column" value="SKU"/> + <argument name="value" value="$createProduct.sku$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index 88bb578712056..2cd2a15b04900 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -132,7 +132,7 @@ <settings> <addField>true</addField> <filter>text</filter> - <bodyTmpl>ui/grid/cells/html</bodyTmpl> + <bodyTmpl>Magento_Catalog/grid/cells/preserved</bodyTmpl> <label translate="true">Name</label> </settings> </column> @@ -155,7 +155,7 @@ <column name="sku" sortOrder="60"> <settings> <filter>text</filter> - <bodyTmpl>ui/grid/cells/html</bodyTmpl> + <bodyTmpl>Magento_Catalog/grid/cells/preserved</bodyTmpl> <label translate="true">SKU</label> </settings> </column> diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/grid/cells/preserved.html b/app/code/Magento/Catalog/view/adminhtml/web/template/grid/cells/preserved.html new file mode 100644 index 0000000000000..936342df23795 --- /dev/null +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/grid/cells/preserved.html @@ -0,0 +1,7 @@ +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="data-grid-cell-content white-space-preserved" html="$col.getLabel($row())"/> diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less index 3e9f2d4401b05..d88260e01b25d 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less @@ -66,6 +66,10 @@ display: inline-block; overflow: hidden; width: 100%; + + &.white-space-preserved { + white-space: pre; + } } body._in-resize { From 7938fb9506178f608fe6d3f5f6c572d8804831fb Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Tue, 2 Mar 2021 11:46:19 -0600 Subject: [PATCH 12/40] B2B-1632: Add MFTF test for MC-38948 - Adding helpers to assert against expected files that match pattern - Adding S3 test for scheduled export --- .../Test/Mftf/Helper/S3FileAssertions.php | 33 +++++++++++++++++ .../Test/Mftf/Helper/LocalFileAssertions.php | 35 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php b/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php index e896901211cb1..96b2d77c951b8 100644 --- a/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php +++ b/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php @@ -149,6 +149,21 @@ public function assertFileExists($filePath, $message = ''): void $this->assertTrue($this->driver->isExists($filePath), $message); } + /** + * Asserts that a file with the given glob pattern exists in the given path on the remote storage system + * + * @param string $path + * @param string $pattern + * @param string $message + * + * @throws \Magento\Framework\Exception\FileSystemException + */ + public function assertSearchedForFileExists($path, $pattern, $message = ""): void + { + $files = $this->driver->search($pattern, $path); + $this->assertNotEmpty($files, $message); + } + /** * Assert a file does not exist on the remote storage system * @@ -206,6 +221,24 @@ public function assertFileContainsString($filePath, $text, $message = ""): void $this->assertStringContainsString($text, $this->driver->fileGetContents($filePath), $message); } + /** + * Asserts that a file with the given glob pattern at the given path on the remote storage system contains a given string + * + * @param string $path + * @param string $pattern + * @param string $text + * @param int $fileIndex + * @param string $message + * @return void + * + * @throws \Magento\Framework\Exception\FileSystemException + */ + public function assertSearchedForFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void + { + $files = $this->driver->search($pattern, $path); + $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex]), $message); + } + /** * Assert a file on the remote storage system does not contain a given string * diff --git a/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php b/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php index ed0e244c280dc..cb12f6a731bb1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php +++ b/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php @@ -134,6 +134,22 @@ public function assertFileExists($filePath, $message = ''): void $this->assertTrue($this->driver->isExists($realPath), $message); } + /** + * Asserts that a file with the given glob pattern exists in the given path + * + * @param string $path + * @param string $pattern + * @param string $message + * + * @throws \Magento\Framework\Exception\FileSystemException + */ + public function assertSearchedForFileExists($path, $pattern, $message = ""): void + { + $realPath = $this->expandPath($path); + $files = $this->driver->search($pattern, $realPath); + $this->assertNotEmpty($files, $message); + } + /** * Assert a file does not exist * @@ -195,6 +211,25 @@ public function assertFileContainsString($filePath, $text, $message = ""): void $this->assertStringContainsString($text, $this->driver->fileGetContents($realPath), $message); } + /** + * Asserts that a file with the given glob pattern at the given path contains a given string + * + * @param string $path + * @param string $pattern + * @param string $text + * @param int $fileIndex + * @param string $message + * @return void + * + * @throws \Magento\Framework\Exception\FileSystemException + */ + public function assertSearchedForFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void + { + $realPath = $this->expandPath($path); + $files = $this->driver->search($pattern, $realPath); + $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex]), $message); + } + /** * Assert a file does not contain a given string * From 13b09134de0df6203ed99b5df7a8e5caa1af11e9 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 2 Mar 2021 14:30:52 -0600 Subject: [PATCH 13/40] PWA-1326: Implement the schema changes for Configurable Options Selection - refactoring swatches --- .../Model/Formatter/OptionValue.php | 11 +------- .../Model/Options/DataProvider/Variant.php | 5 ++-- .../SwatchesGraphQl/etc/schema.graphqls | 2 +- .../Swatches/ProductSwatchDataTest.php | 28 ++++++++++++++++--- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php index f171514a37897..5d721f13fbb9d 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Formatter/OptionValue.php @@ -11,7 +11,6 @@ use Magento\CatalogInventory\Model\StockRegistry; use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute; use Magento\ConfigurableProductGraphQl\Model\Options\SelectionUidFormatter; -use Magento\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider\SwatchDataProvider; /** * Formatter for configurable product option values @@ -23,11 +22,6 @@ class OptionValue */ private $selectionUidFormatter; - /** - * @var SwatchDataProvider - */ - private $swatchDataProvider; - /** * @var StockRegistry */ @@ -35,16 +29,13 @@ class OptionValue /** * @param SelectionUidFormatter $selectionUidFormatter - * @param SwatchDataProvider $swatchDataProvider * @param StockRegistry $stockRegistry */ public function __construct( SelectionUidFormatter $selectionUidFormatter, - SwatchDataProvider $swatchDataProvider, StockRegistry $stockRegistry ) { $this->selectionUidFormatter = $selectionUidFormatter; - $this->swatchDataProvider = $swatchDataProvider; $this->stockRegistry = $stockRegistry; } @@ -69,7 +60,7 @@ public function format(array $optionValue, Attribute $attribute, array $optionId 'is_available' => $this->getIsAvailable($optionIds[$valueIndex] ?? []), 'is_use_default' => (bool)$attribute->getIsUseDefault(), 'label' => $optionValue['label'], - 'swatch' => $this->swatchDataProvider->getData($optionValue['value_index']) + 'value_index' => $optionValue['value_index'] ]; } diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php index 71671353facf5..7b5a3fb806a5f 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Options/DataProvider/Variant.php @@ -10,7 +10,6 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -use Magento\Framework\DataObject; use Magento\Framework\Exception\LocalizedException; /** @@ -44,8 +43,8 @@ public function __construct( * Load available child products by parent * * @param ProductInterface $product - * @return DataObject[] - * @throws LocalizedException + * @return ProductInterface[] + * @throws \Magento\Framework\Exception\LocalizedException */ public function getSalableVariantsByParent(ProductInterface $product): array { diff --git a/app/code/Magento/SwatchesGraphQl/etc/schema.graphqls b/app/code/Magento/SwatchesGraphQl/etc/schema.graphqls index 35f6265093990..3491568108daf 100644 --- a/app/code/Magento/SwatchesGraphQl/etc/schema.graphqls +++ b/app/code/Magento/SwatchesGraphQl/etc/schema.graphqls @@ -49,5 +49,5 @@ type ColorSwatchData implements SwatchDataInterface { } type ConfigurableProductOptionValue { - swatch: SwatchDataInterface + swatch: SwatchDataInterface @resolver(class: "Magento\\SwatchesGraphQl\\Model\\Resolver\\Product\\Options\\SwatchData") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php index ae34ea31f0d51..6c02882af8ecc 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php @@ -84,12 +84,12 @@ public function testVisualSwatchDataValues() $color = '#000000'; $query = <<<QUERY { - products(filter: {sku: {eq: "$productSku"}}) { + products(filter: { sku: { eq: "$productSku" } }) { items { - ... on ConfigurableProduct{ - configurable_options{ + ... on ConfigurableProduct { + configurable_options { values { - swatch_data{ + swatch_data { value ... on ImageSwatchData { thumbnail @@ -97,6 +97,16 @@ public function testVisualSwatchDataValues() } } } + configurable_product_options_selection { + configurable_options { + values { + label + swatch { + value + } + } + } + } } } } @@ -123,5 +133,15 @@ public function testVisualSwatchDataValues() $option['values'][1]['swatch_data']['thumbnail'], $this->swatchMediaHelper->getSwatchAttributeImage(Swatch::SWATCH_THUMBNAIL_NAME, $imageName) ); + + $configurableProductOptionsSelection = + $product['configurable_product_options_selection']['configurable_options'][0]; + + $this->assertArrayHasKey('values', $configurableProductOptionsSelection); + $this->assertEquals($color, $configurableProductOptionsSelection['values'][0]['swatch']['value']); + $this->assertStringContainsString( + $configurableProductOptionsSelection['values'][1]['swatch']['value'], + $this->swatchMediaHelper->getSwatchAttributeImage(Swatch::SWATCH_IMAGE_NAME, $imageName) + ); } } From 0794361529e349d8f52620e083eb92bf3dc0121e Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Tue, 2 Mar 2021 16:05:31 -0600 Subject: [PATCH 14/40] PWA-1326: Implement the schema changes for Configurable Options Selection - add test for swatches --- .../Magento/GraphQl/Swatches/ProductSwatchDataTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php index 6c02882af8ecc..713a16a6bfaa9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Swatches/ProductSwatchDataTest.php @@ -103,6 +103,9 @@ public function testVisualSwatchDataValues() label swatch { value + ... on ImageSwatchData { + thumbnail + } } } } @@ -143,5 +146,9 @@ public function testVisualSwatchDataValues() $configurableProductOptionsSelection['values'][1]['swatch']['value'], $this->swatchMediaHelper->getSwatchAttributeImage(Swatch::SWATCH_IMAGE_NAME, $imageName) ); + $this->assertEquals( + $configurableProductOptionsSelection['values'][1]['swatch']['thumbnail'], + $this->swatchMediaHelper->getSwatchAttributeImage(Swatch::SWATCH_THUMBNAIL_NAME, $imageName) + ); } } From 1ac7ca68fd3d7d66ccc7a10deb620fbfb1513250 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Wed, 3 Mar 2021 09:54:24 -0600 Subject: [PATCH 15/40] B2B-1632: Add MFTF test for MC-38948 - Addressing CR feedback --- app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php | 4 ++-- .../Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php b/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php index 96b2d77c951b8..53cb65e9fed5d 100644 --- a/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php +++ b/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php @@ -158,7 +158,7 @@ public function assertFileExists($filePath, $message = ''): void * * @throws \Magento\Framework\Exception\FileSystemException */ - public function assertSearchedForFileExists($path, $pattern, $message = ""): void + public function assertGlobbedFileExists($path, $pattern, $message = ""): void { $files = $this->driver->search($pattern, $path); $this->assertNotEmpty($files, $message); @@ -233,7 +233,7 @@ public function assertFileContainsString($filePath, $text, $message = ""): void * * @throws \Magento\Framework\Exception\FileSystemException */ - public function assertSearchedForFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void + public function assertGlobbedFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void { $files = $this->driver->search($pattern, $path); $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex]), $message); diff --git a/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php b/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php index cb12f6a731bb1..530abb1ccbd46 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php +++ b/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php @@ -143,7 +143,7 @@ public function assertFileExists($filePath, $message = ''): void * * @throws \Magento\Framework\Exception\FileSystemException */ - public function assertSearchedForFileExists($path, $pattern, $message = ""): void + public function assertGlobbedFileExists($path, $pattern, $message = ""): void { $realPath = $this->expandPath($path); $files = $this->driver->search($pattern, $realPath); @@ -223,7 +223,7 @@ public function assertFileContainsString($filePath, $text, $message = ""): void * * @throws \Magento\Framework\Exception\FileSystemException */ - public function assertSearchedForFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void + public function assertGlobbedFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void { $realPath = $this->expandPath($path); $files = $this->driver->search($pattern, $realPath); From 092cdf780f16159052db9d31ec886fe7542c5515 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 3 Mar 2021 14:35:03 -0600 Subject: [PATCH 16/40] PWA-1326: Implement the schema changes for Configurable Options Selection - configurable product suggest --- app/code/Magento/SwatchesGraphQl/composer.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SwatchesGraphQl/composer.json b/app/code/Magento/SwatchesGraphQl/composer.json index 8b6651f89f3b7..5b50a10abfe2b 100644 --- a/app/code/Magento/SwatchesGraphQl/composer.json +++ b/app/code/Magento/SwatchesGraphQl/composer.json @@ -7,7 +7,10 @@ "magento/framework": "*", "magento/module-swatches": "*", "magento/module-catalog": "*", - "magento/module-catalog-graph-ql": "*", + "magento/module-catalog-graph-ql": "*" + + }, + "suggest": { "magento/module-configurable-product-graph-ql": "*" }, "license": [ From 850313d87cbd7de65419dc1b6d44790aa1809caf Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 4 Mar 2021 09:28:28 -0600 Subject: [PATCH 17/40] PWA-1326: Implement the schema changes for Configurable Options Selection - static --- app/code/Magento/SwatchesGraphQl/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/SwatchesGraphQl/composer.json b/app/code/Magento/SwatchesGraphQl/composer.json index 5b50a10abfe2b..959f0f201d2b3 100644 --- a/app/code/Magento/SwatchesGraphQl/composer.json +++ b/app/code/Magento/SwatchesGraphQl/composer.json @@ -8,7 +8,6 @@ "magento/module-swatches": "*", "magento/module-catalog": "*", "magento/module-catalog-graph-ql": "*" - }, "suggest": { "magento/module-configurable-product-graph-ql": "*" From ef7092916d7f75a6d002e860c7e4fcb6a829a7bf Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Fri, 5 Mar 2021 10:54:45 +0200 Subject: [PATCH 18/40] MC-40873: Product is shown as Out of Stock on CMS page when Category Permissions are enabled --- .../Magento/Catalog/Block/Ui/ProductViewCounter.php | 1 + .../view/base/web/js/product/addtocart-button.js | 10 ++++++++++ .../web/template/product/addtocart-button.html | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php b/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php index c5c08a0552f42..93732b1b52f0c 100644 --- a/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php +++ b/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php @@ -153,6 +153,7 @@ public function getCurrentProductData() $this->productRenderCollectorComposite ->collect($product, $productRender); $data = $this->hydrator->extract($productRender); + $data['is_available'] = $product->isAvailable(); $currentProductData = [ 'items' => [ diff --git a/app/code/Magento/Catalog/view/base/web/js/product/addtocart-button.js b/app/code/Magento/Catalog/view/base/web/js/product/addtocart-button.js index 4baf082b37c02..f599d05ba5ea9 100644 --- a/app/code/Magento/Catalog/view/base/web/js/product/addtocart-button.js +++ b/app/code/Magento/Catalog/view/base/web/js/product/addtocart-button.js @@ -55,6 +55,16 @@ define([ return row['is_salable']; }, + /** + * Depends on this option, stock status text can be "In stock" or "Out Of Stock" + * + * @param {Object} row + * @returns {Boolean} + */ + isAvailable: function (row) { + return row['is_available']; + }, + /** * Depends on this option, "Add to cart" button can be shown or hide. Depends on backend configuration * diff --git a/app/code/Magento/Catalog/view/frontend/web/template/product/addtocart-button.html b/app/code/Magento/Catalog/view/frontend/web/template/product/addtocart-button.html index 05dbf02703285..867b5f40d98db 100644 --- a/app/code/Magento/Catalog/view/frontend/web/template/product/addtocart-button.html +++ b/app/code/Magento/Catalog/view/frontend/web/template/product/addtocart-button.html @@ -15,10 +15,10 @@ </button> </if> - <ifnot args="isSalable($row())"> + <if args="isAvailable($row()) === false"> <div class="stock unavailable"> <text args="$t('Availability')"/> <span translate="'Out of stock'"/> </div> - </ifnot> + </if> </if> From 05b4665ce56a3f231bfddd766a9a003134d23681 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Fri, 5 Mar 2021 13:14:26 +0200 Subject: [PATCH 19/40] MC-40873: Product is shown as Out of Stock on CMS page when Category Permissions are enabled --- .../Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php index 6026d1462e461..87f5be4b21333 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php @@ -166,6 +166,7 @@ public function testGetCurrentProductDataWithNonEmptyProduct() { $productMock = $this->getMockBuilder(ProductInterface::class) ->disableOriginalConstructor() + ->addMethods(['isAvailable']) ->getMockForAbstractClass(); $productRendererMock = $this->getMockBuilder(ProductRenderInterface::class) ->disableOriginalConstructor() @@ -173,7 +174,6 @@ public function testGetCurrentProductDataWithNonEmptyProduct() $storeMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->getMock(); - $this->registryMock->expects($this->once()) ->method('registry') ->with('product') From 9d666ccbac83a9678a3c7d7d5bd80bd67c764cc2 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Fri, 5 Mar 2021 16:01:39 +0200 Subject: [PATCH 20/40] MC-41069: Free Shipping enables with wrong total for DHL --- .../Model/Carrier/AbstractCarrierOnline.php | 12 ++- .../Magento/Dhl/Model/CarrierTest.php | 102 ++++++++++++++++-- 2 files changed, 105 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php index c2238ff1a3809..c2331b294769a 100644 --- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php +++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php @@ -648,13 +648,23 @@ public function setRawRequest($request) */ public function getMethodPrice($cost, $method = '') { + if ($method == $this->getConfigData( + $this->_freeMethod + ) && $this->getConfigFlag( + 'free_shipping_enable' + ) && $this->getConfigData( + 'free_shipping_subtotal' + ) <= $this->_request->getBaseSubtotalWithDiscountInclTax()) { + return '0.00'; + } + return $method == $this->getConfigData( $this->_freeMethod ) && $this->getConfigFlag( 'free_shipping_enable' ) && $this->getConfigData( 'free_shipping_subtotal' - ) <= $this->_rawRequest->getBaseSubtotalInclTax() ? '0.00' : $this->getFinalPriceWithHandlingFee( + ) <= $this->_request->getBaseSubtotalWithDiscountInclTax() ? '0.00' : $this->getFinalPriceWithHandlingFee( $cost ); } diff --git a/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php b/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php index 552040489e253..af236b5d5212f 100644 --- a/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php +++ b/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php @@ -443,14 +443,7 @@ private function getExpectedLabelRequestXml( public function testCollectRates() { $requestData = $this->getRequestData(); - //phpcs:disable Magento2.Functions.DiscouragedFunction - $response = new Response( - 200, - [], - file_get_contents(__DIR__ . '/../_files/dhl_quote_response.xml') - ); - //phpcs:enable Magento2.Functions.DiscouragedFunction - $this->httpClient->nextResponses(array_fill(0, Carrier::UNAVAILABLE_DATE_LOOK_FORWARD + 1, $response)); + $this->setNextResponse(__DIR__ . '/../_files/dhl_quote_response.xml'); /** @var RateRequest $request */ $request = Bootstrap::getObjectManager()->create(RateRequest::class, $requestData); $expectedRates = [ @@ -563,6 +556,80 @@ private function setDhlConfig(array $params) } } + /** + * Tests that the free rate is returned when sending a quotes request + * + * @param array $addRequestData + * @param bool $freeShippingExpects + * @magentoConfigFixture default_store carriers/dhl/active 1 + * @magentoConfigFixture default_store carriers/dhl/id some ID + * @magentoConfigFixture default_store carriers/dhl/shipment_days Mon,Tue,Wed,Thu,Fri,Sat + * @magentoConfigFixture default_store carriers/dhl/intl_shipment_days Mon,Tue,Wed,Thu,Fri,Sat + * @magentoConfigFixture default_store carriers/dhl/allowed_methods IE + * @magentoConfigFixture default_store carriers/dhl/international_service IE + * @magentoConfigFixture default_store carriers/dhl/gateway_url https://xmlpi-ea.dhl.com/XMLShippingServlet + * @magentoConfigFixture default_store carriers/dhl/id some ID + * @magentoConfigFixture default_store carriers/dhl/password some password + * @magentoConfigFixture default_store carriers/dhl/content_type N + * @magentoConfigFixture default_store carriers/dhl/nondoc_methods 1,3,4,8,P,Q,E,F,H,J,M,V,Y + * @magentoConfigFixture default_store carriers/dhl/showmethod' => 1, + * @magentoConfigFixture default_store carriers/dhl/title DHL Title + * @magentoConfigFixture default_store carriers/dhl/specificerrmsg dhl error message + * @magentoConfigFixture default_store carriers/dhl/unit_of_measure K + * @magentoConfigFixture default_store carriers/dhl/size 1 + * @magentoConfigFixture default_store carriers/dhl/height 1.6 + * @magentoConfigFixture default_store carriers/dhl/width 1.6 + * @magentoConfigFixture default_store carriers/dhl/depth 1.6 + * @magentoConfigFixture default_store carriers/dhl/debug 1 + * @magentoConfigFixture default_store carriers/dhl/free_method_nondoc P + * @magentoConfigFixture default_store carriers/dhl/free_shipping_enable 1 + * @magentoConfigFixture default_store carriers/dhl/free_shipping_subtotal 25 + * @magentoConfigFixture default_store shipping/origin/country_id GB + * @magentoAppIsolation enabled + * @dataProvider collectRatesWithFreeShippingDataProvider + */ + public function testCollectRatesWithFreeShipping(array $addRequestData, bool $freeShippingExpects): void + { + $this->setNextResponse(__DIR__ . '/../_files/dhl_quote_response.xml'); + + $requestData = $this->getRequestData(); + $requestData['data'] += $addRequestData; + /** @var RateRequest $request */ + $request = Bootstrap::getObjectManager()->create(RateRequest::class, $requestData); + + $actualRates = $this->dhlCarrier->collectRates($request)->getAllRates(); + $freeRateExists = false; + foreach ($actualRates as $i => $actualRate) { + $actualRate = $actualRate->getData(); + if ($actualRate['method'] === 'P' && $actualRate['price'] === 0.0) { + $freeRateExists = true; + } + } + + self::assertEquals($freeShippingExpects, $freeRateExists); + } + + /** + * @return array + */ + public function collectRatesWithFreeShippingDataProvider(): array + { + return [ + [ + ['base_subtotal_incl_tax' => 25, 'base_subtotal_with_discount_incl_tax' => 22], + false + ], + [ + ['base_subtotal_incl_tax' => 25, 'base_subtotal_with_discount_incl_tax' => 25], + true + ], + [ + ['base_subtotal_incl_tax' => 28, 'base_subtotal_with_discount_incl_tax' => 25], + true + ], + ]; + } + /** * Returns request data. * @@ -614,4 +681,23 @@ private function getRequestData(): array ] ]; } + + /** + * Set next response content from file + * + * @param string $file + */ + private function setNextResponse(string $file): void + { + //phpcs:disable Magento2.Functions.DiscouragedFunction + $response = new Response( + 200, + [], + file_get_contents($file) + ); + //phpcs:enable Magento2.Functions.DiscouragedFunction + $this->httpClient->nextResponses( + array_fill(0, Carrier::UNAVAILABLE_DATE_LOOK_FORWARD + 1, $response) + ); + } } From 01dd146c79c0d25884eaa18a8962717ac710f06e Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Fri, 5 Mar 2021 16:02:20 +0200 Subject: [PATCH 21/40] MC-41069: Free Shipping enables with wrong total for DHL --- .../Shipping/Model/Carrier/AbstractCarrierOnline.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php index c2331b294769a..45ccf38a95ef0 100644 --- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php +++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php @@ -648,16 +648,6 @@ public function setRawRequest($request) */ public function getMethodPrice($cost, $method = '') { - if ($method == $this->getConfigData( - $this->_freeMethod - ) && $this->getConfigFlag( - 'free_shipping_enable' - ) && $this->getConfigData( - 'free_shipping_subtotal' - ) <= $this->_request->getBaseSubtotalWithDiscountInclTax()) { - return '0.00'; - } - return $method == $this->getConfigData( $this->_freeMethod ) && $this->getConfigFlag( From 33b7c95a5c62cd50bce136b0ae62f667ac77fd7e Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Tue, 9 Mar 2021 10:25:16 +0200 Subject: [PATCH 22/40] MC-41069: Free Shipping enables with wrong total for DHL --- .../Model/Carrier/AbstractCarrierOnline.php | 2 +- .../Magento/Dhl/Model/CarrierTest.php | 125 +++++++++--------- 2 files changed, 66 insertions(+), 61 deletions(-) diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php index 45ccf38a95ef0..f88fecf84be6a 100644 --- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php +++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php @@ -654,7 +654,7 @@ public function getMethodPrice($cost, $method = '') 'free_shipping_enable' ) && $this->getConfigData( 'free_shipping_subtotal' - ) <= $this->_request->getBaseSubtotalWithDiscountInclTax() ? '0.00' : $this->getFinalPriceWithHandlingFee( + ) <= $this->_rawRequest->getValueWithDiscount() ? '0.00' : $this->getFinalPriceWithHandlingFee( $cost ); } diff --git a/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php b/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php index af236b5d5212f..57c6042ca25c9 100644 --- a/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php +++ b/dev/tests/integration/testsuite/Magento/Dhl/Model/CarrierTest.php @@ -442,10 +442,8 @@ private function getExpectedLabelRequestXml( */ public function testCollectRates() { - $requestData = $this->getRequestData(); $this->setNextResponse(__DIR__ . '/../_files/dhl_quote_response.xml'); - /** @var RateRequest $request */ - $request = Bootstrap::getObjectManager()->create(RateRequest::class, $requestData); + $request = $this->createRequest(); $expectedRates = [ ['carrier' => 'dhl', 'carrier_title' => 'DHL Title', 'cost' => 45.85, 'method' => 'E', 'price' => 45.85], ['carrier' => 'dhl', 'carrier_title' => 'DHL Title', 'cost' => 35.26, 'method' => 'Q', 'price' => 35.26], @@ -480,11 +478,9 @@ public function testCollectRates() */ public function testCollectRatesWithoutDimensions(?string $size, ?string $height, ?string $width, ?string $depth) { - $requestData = $this->getRequestData(); $this->setDhlConfig(['size' => $size, 'height' => $height, 'width' => $width, 'depth' => $depth]); - /** @var RateRequest $request */ - $request = Bootstrap::getObjectManager()->create(RateRequest::class, $requestData); + $request = $this->createRequest(); $this->dhlCarrier = Bootstrap::getObjectManager()->create(Carrier::class); $this->dhlCarrier->collectRates($request)->getAllRates(); @@ -504,15 +500,13 @@ public function testCollectRatesWithoutDimensions(?string $size, ?string $height public function testGetRatesWithHttpException(): void { $this->setDhlConfig(['showmethod' => 1]); - $requestData = $this->getRequestData(); $deferredResponse = $this->getMockBuilder(HttpResponseDeferredInterface::class) ->onlyMethods(['get']) ->getMockForAbstractClass(); $exception = new HttpException('Exception message'); $deferredResponse->method('get')->willThrowException($exception); $this->httpClient->setDeferredResponseMock($deferredResponse); - /** @var RateRequest $request */ - $request = Bootstrap::getObjectManager()->create(RateRequest::class, $requestData); + $request = $this->createRequest(); $this->dhlCarrier = Bootstrap::getObjectManager()->create(Carrier::class); $resultRate = $this->dhlCarrier->collectRates($request)->getAllRates()[0]; $error = Bootstrap::getObjectManager()->get(Error::class); @@ -591,18 +585,15 @@ private function setDhlConfig(array $params) public function testCollectRatesWithFreeShipping(array $addRequestData, bool $freeShippingExpects): void { $this->setNextResponse(__DIR__ . '/../_files/dhl_quote_response.xml'); - - $requestData = $this->getRequestData(); - $requestData['data'] += $addRequestData; - /** @var RateRequest $request */ - $request = Bootstrap::getObjectManager()->create(RateRequest::class, $requestData); + $request = $this->createRequest($addRequestData); $actualRates = $this->dhlCarrier->collectRates($request)->getAllRates(); $freeRateExists = false; - foreach ($actualRates as $i => $actualRate) { + foreach ($actualRates as $actualRate) { $actualRate = $actualRate->getData(); - if ($actualRate['method'] === 'P' && $actualRate['price'] === 0.0) { + if ($actualRate['method'] === 'P' && (float)$actualRate['price'] === 0.0) { $freeRateExists = true; + break; } } @@ -616,15 +607,15 @@ public function collectRatesWithFreeShippingDataProvider(): array { return [ [ - ['base_subtotal_incl_tax' => 25, 'base_subtotal_with_discount_incl_tax' => 22], + ['package_value' => 25, 'package_value_with_discount' => 22], false ], [ - ['base_subtotal_incl_tax' => 25, 'base_subtotal_with_discount_incl_tax' => 25], + ['package_value' => 25, 'package_value_with_discount' => 25], true ], [ - ['base_subtotal_incl_tax' => 28, 'base_subtotal_with_discount_incl_tax' => 25], + ['package_value' => 28, 'package_value_with_discount' => 25], true ], ]; @@ -638,47 +629,45 @@ public function collectRatesWithFreeShippingDataProvider(): array private function getRequestData(): array { return [ - 'data' => [ - 'dest_country_id' => 'DE', - 'dest_region_id' => '82', - 'dest_region_code' => 'BER', - 'dest_street' => 'Turmstraße 17', - 'dest_city' => 'Berlin', - 'dest_postcode' => '10559', - 'dest_postal' => '10559', - 'package_value' => '5', - 'package_value_with_discount' => '5', - 'package_weight' => '8.2657', - 'package_qty' => '1', - 'package_physical_value' => '5', - 'free_method_weight' => '5', - 'store_id' => '1', - 'website_id' => '1', - 'free_shipping' => '0', - 'limit_carrier' => null, - 'base_subtotal_incl_tax' => '5', - 'orig_country_id' => 'US', - 'orig_region_id' => '12', - 'orig_city' => 'Fremont', - 'orig_postcode' => '94538', - 'dhl_id' => 'MAGEN_8501', - 'dhl_password' => 'QR2GO1U74X', - 'dhl_account' => '799909537', - 'dhl_shipping_intl_key' => '54233F2B2C4E5C4B4C5E5A59565530554B405641475D5659', - 'girth' => null, - 'height' => null, - 'length' => null, - 'width' => null, - 'weight' => 1, - 'dhl_shipment_type' => 'P', - 'dhl_duitable' => 0, - 'dhl_duty_payment_type' => 'R', - 'dhl_content_desc' => 'Big Box', - 'limit_method' => 'IE', - 'ship_date' => '2014-01-09', - 'action' => 'RateEstimate', - 'all_items' => [], - ] + 'dest_country_id' => 'DE', + 'dest_region_id' => '82', + 'dest_region_code' => 'BER', + 'dest_street' => 'Turmstraße 17', + 'dest_city' => 'Berlin', + 'dest_postcode' => '10559', + 'dest_postal' => '10559', + 'package_value' => '5', + 'package_value_with_discount' => '5', + 'package_weight' => '8.2657', + 'package_qty' => '1', + 'package_physical_value' => '5', + 'free_method_weight' => '5', + 'store_id' => '1', + 'website_id' => '1', + 'free_shipping' => '0', + 'limit_carrier' => null, + 'base_subtotal_incl_tax' => '5', + 'orig_country_id' => 'US', + 'orig_region_id' => '12', + 'orig_city' => 'Fremont', + 'orig_postcode' => '94538', + 'dhl_id' => 'MAGEN_8501', + 'dhl_password' => 'QR2GO1U74X', + 'dhl_account' => '799909537', + 'dhl_shipping_intl_key' => '54233F2B2C4E5C4B4C5E5A59565530554B405641475D5659', + 'girth' => null, + 'height' => null, + 'length' => null, + 'width' => null, + 'weight' => 1, + 'dhl_shipment_type' => 'P', + 'dhl_duitable' => 0, + 'dhl_duty_payment_type' => 'R', + 'dhl_content_desc' => 'Big Box', + 'limit_method' => 'IE', + 'ship_date' => '2014-01-09', + 'action' => 'RateEstimate', + 'all_items' => [], ]; } @@ -700,4 +689,20 @@ private function setNextResponse(string $file): void array_fill(0, Carrier::UNAVAILABLE_DATE_LOOK_FORWARD + 1, $response) ); } + + /** + * Create Rate Request + * + * @param array $addRequestData + * @return RateRequest + */ + private function createRequest(array $addRequestData = []): RateRequest + { + $requestData = $this->getRequestData(); + if (!empty($addRequestData)) { + $requestData = array_merge($requestData, $addRequestData); + } + + return Bootstrap::getObjectManager()->create(RateRequest::class, ['data' => $requestData]); + } } From e9f7a3cf86fb9e55272514be2de3f2a20d6f2570 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Tue, 9 Mar 2021 02:44:11 -0600 Subject: [PATCH 23/40] B2B-1701: Deprecate database media storage function - Added deprecated tags on related db classes --- .../Magento/MediaStorage/Helper/File/Storage/Database.php | 5 +++++ .../Model/Config/Backend/Storage/Media/Database.php | 4 +++- .../Model/Config/Source/Storage/Media/Database.php | 3 +++ .../Model/Config/Source/Storage/Media/Storage.php | 4 ++++ .../Magento/MediaStorage/Model/File/Storage/Database.php | 2 ++ .../Model/File/Storage/Database/AbstractDatabase.php | 5 ++++- .../MediaStorage/Model/File/Storage/Directory/Database.php | 2 ++ .../Model/ResourceModel/File/Storage/AbstractStorage.php | 2 ++ .../Model/ResourceModel/File/Storage/Database.php | 2 ++ .../Model/ResourceModel/File/Storage/Directory/Database.php | 2 ++ 10 files changed, 29 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index 05e2e836abada..ab9bdc84011b7 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -14,6 +14,9 @@ * * @api * @since 100.0.2 + * + * @deprecated Database Media storage is deprecated + * */ class Database extends \Magento\Framework\App\Helper\AbstractHelper { @@ -140,6 +143,7 @@ public function getResourceStorageModel() public function saveFile($filename) { if ($this->checkDbUsage()) { + trigger_error('Class is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->saveFile($this->_removeAbsPathFromFileName($filename)); } } @@ -171,6 +175,7 @@ public function renameFile($oldName, $newName) public function copyFile($oldName, $newName) { if ($this->checkDbUsage()) { + trigger_error('Class is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->copyFile( $this->_removeAbsPathFromFileName($oldName), $this->_removeAbsPathFromFileName($newName) diff --git a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php index 1a55be299a75b..131777c9beb94 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php @@ -4,7 +4,9 @@ * See COPYING.txt for license details. */ namespace Magento\MediaStorage\Model\Config\Backend\Storage\Media; - +/** +* @deprecated Database Media storage is deprecated +**/ class Database extends \Magento\Framework\App\Config\Value { /** diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php index 83134c2ac00ef..1d1e98299ee23 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php @@ -12,6 +12,9 @@ use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Config\ConfigOptionsListConstants; +/** + * @deprecated Database Media storage is deprecated + **/ class Database implements \Magento\Framework\Option\ArrayInterface { /** diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php index fb171831407e2..a19e7cd69fbfb 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php @@ -9,6 +9,10 @@ */ namespace Magento\MediaStorage\Model\Config\Source\Storage\Media; + +/** + * @deprecated Database Media storage is deprecated + **/ class Storage implements \Magento\Framework\Option\ArrayInterface { /** diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php index 2bdc69f45ccb8..c11d54523544d 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php @@ -10,6 +10,8 @@ * * @api * @since 100.0.2 + * + * @deprecated Database Media storage is deprecated */ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase { diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php index c9812b86e8b91..34628718fddae 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php @@ -7,7 +7,10 @@ /** * Class AbstractDatabase - */ + * + * @deprecated Database Media storage is deprecated + * + **/ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel { /** diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php index 2617e88e7538a..96db61a6398f3 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php @@ -11,6 +11,8 @@ * * @api * @since 100.0.2 + * + * @deprecated Database Media storage is deprecated */ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php index 227b428328b79..81cbc44fcf326 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php @@ -7,6 +7,8 @@ /** * Class AbstractStorage + * + * @deprecated Database Media storage is deprecated */ abstract class AbstractStorage extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php index ae896395b8eb5..1fa593d7c832a 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php @@ -10,6 +10,8 @@ * * @api * @since 100.0.2 + * + * @deprecated Database Media storage is deprecated */ class Database extends \Magento\MediaStorage\Model\ResourceModel\File\Storage\AbstractStorage { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php index e5f54cac4af6a..6ff011d25d802 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php @@ -7,6 +7,8 @@ /** * Class Database + * + * @deprecated Database Media storage is deprecated */ class Database extends \Magento\MediaStorage\Model\ResourceModel\File\Storage\AbstractStorage { From 397e33bcee3a09b606e696fda5430d66c36c2bf5 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Tue, 9 Mar 2021 10:56:06 +0200 Subject: [PATCH 24/40] MC-41069: Free Shipping enables with wrong total for DHL --- app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php index daff459d7ba3f..07da63fa8476e 100644 --- a/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php @@ -226,7 +226,7 @@ public function testGetMethodPrice( ->willReturn($freeShippingEnabled); $request = new RateRequest(); - $request->setBaseSubtotalInclTax($requestSubtotal); + $request->setValueWithDiscount($requestSubtotal); $this->model->setRawRequest($request); $price = $this->model->getMethodPrice($cost, $shippingMethod); $this->assertEquals($expectedPrice, $price); From f802f7c0182ef7bac6306f002fe75b10322440a6 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Tue, 9 Mar 2021 10:11:22 -0600 Subject: [PATCH 25/40] B2B-1632: Add MFTF test for MC-38948 - Addressing PR feedback --- .../Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php b/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php index 530abb1ccbd46..dbf777c1fe5c5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php +++ b/app/code/Magento/Catalog/Test/Mftf/Helper/LocalFileAssertions.php @@ -227,7 +227,7 @@ public function assertGlobbedFileContainsString($path, $pattern, $text, $fileInd { $realPath = $this->expandPath($path); $files = $this->driver->search($pattern, $realPath); - $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex]), $message); + $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex] ?? ''), $message); } /** From 0fa62d00821810ee2e19de98e57c9cbe4e6e7263 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Tue, 9 Mar 2021 14:10:50 -0600 Subject: [PATCH 26/40] B2B-1632: Add MFTF test for MC-38948 - Addressing PR feedback --- app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php b/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php index 53cb65e9fed5d..cec553afe9463 100644 --- a/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php +++ b/app/code/Magento/AwsS3/Test/Mftf/Helper/S3FileAssertions.php @@ -236,7 +236,7 @@ public function assertFileContainsString($filePath, $text, $message = ""): void public function assertGlobbedFileContainsString($path, $pattern, $text, $fileIndex = 0, $message = ""): void { $files = $this->driver->search($pattern, $path); - $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex]), $message); + $this->assertStringContainsString($text, $this->driver->fileGetContents($files[$fileIndex] ?? ''), $message); } /** From ada9927c1af52836b989cdbb6537269661219398 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Tue, 9 Mar 2021 14:54:53 -0600 Subject: [PATCH 27/40] B2B-1701: Deprecate database media storage function - Added removed trigger errors on class deprecation --- app/code/Magento/MediaStorage/Helper/File/Storage/Database.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index ab9bdc84011b7..61a082fc6c846 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -143,7 +143,6 @@ public function getResourceStorageModel() public function saveFile($filename) { if ($this->checkDbUsage()) { - trigger_error('Class is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->saveFile($this->_removeAbsPathFromFileName($filename)); } } @@ -175,7 +174,6 @@ public function renameFile($oldName, $newName) public function copyFile($oldName, $newName) { if ($this->checkDbUsage()) { - trigger_error('Class is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->copyFile( $this->_removeAbsPathFromFileName($oldName), $this->_removeAbsPathFromFileName($newName) From 61ef125f9b38afbe3a0747fd30c825a0853ff947 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Tue, 9 Mar 2021 15:43:35 -0600 Subject: [PATCH 28/40] B2B-1701: Deprecate database media storage function - Test to verify trigger errors on class deprecation --- app/code/Magento/MediaStorage/Helper/File/Storage/Database.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index 61a082fc6c846..04896961f0c87 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -143,6 +143,7 @@ public function getResourceStorageModel() public function saveFile($filename) { if ($this->checkDbUsage()) { + trigger_error('Database media storage function is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->saveFile($this->_removeAbsPathFromFileName($filename)); } } @@ -174,6 +175,7 @@ public function renameFile($oldName, $newName) public function copyFile($oldName, $newName) { if ($this->checkDbUsage()) { + trigger_error('Database media storage function is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->copyFile( $this->_removeAbsPathFromFileName($oldName), $this->_removeAbsPathFromFileName($newName) From 58f21ca8cd3857b76a7e305a2ca2dc3c8c0ed9d7 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Tue, 9 Mar 2021 23:16:45 -0600 Subject: [PATCH 29/40] B2B-1701: Deprecate database media storage function - Added config file deprecation --- .../MediaStorage/Model/Config/Source/Storage/Media/Storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php index a19e7cd69fbfb..657188b82e752 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php @@ -27,7 +27,7 @@ public function toOptionArray() 'value' => \Magento\MediaStorage\Model\File\Storage::STORAGE_MEDIA_FILE_SYSTEM, 'label' => __('File System'), ], - ['value' => \Magento\MediaStorage\Model\File\Storage::STORAGE_MEDIA_DATABASE, 'label' => __('Database')] + ['value' => \Magento\MediaStorage\Model\File\Storage::STORAGE_MEDIA_DATABASE, 'label' => __('Database(Deprecated)')] ]; } } From 1e5fa8ff03f35a72a3d8fcf4728bd8d743f6ec38 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Wed, 10 Mar 2021 14:41:34 +0200 Subject: [PATCH 30/40] MC-41138: W3C validator reports duplicate ID on Listing Page and Search Result Page --- .../frontend/templates/product/list.phtml | 2 +- .../templates/product/list/toolbar.phtml | 28 ++++++++----------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml index a831bd7be6f71..4fba22f41c9de 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml @@ -153,7 +153,7 @@ $_helper = $block->getData('outputHelper'); <?php endforeach; ?> </ol> </div> - <?= $block->getToolbarHtml() ?> + <?= $block->getChildBlock('toolbar')->setIsBottom(true)->toHtml() ?> <script type="text/x-magento-init"> { "[data-role=tocart-form], .form.map.checkout": { diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml index 76ef6baf4993e..3c8687d090baf 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/toolbar.phtml @@ -10,27 +10,23 @@ * * @var $block \Magento\Catalog\Block\Product\ProductList\Toolbar */ - -// phpcs:disable Magento2.Security.IncludeFile.FoundIncludeFile -// phpcs:disable PSR2.Methods.FunctionCallSignature.SpaceBeforeOpenBracket ?> <?php if ($block->getCollection()->getSize()) :?> <?php $widget = $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonDecode($block->getWidgetOptionsJson()); $widgetOptions = $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($widget['productListToolbarForm']); ?> <div class="toolbar toolbar-products" data-mage-init='{"productListToolbarForm":<?= /* @noEscape */ $widgetOptions ?>}'> - <?php if ($block->isExpanded()) :?> - <?php include ($block->getTemplateFile('Magento_Catalog::product/list/toolbar/viewmode.phtml')) ?> - <?php endif; ?> - - <?php include ($block->getTemplateFile('Magento_Catalog::product/list/toolbar/amount.phtml')) ?> - - <?= $block->getPagerHtml() ?> - - <?php include ($block->getTemplateFile('Magento_Catalog::product/list/toolbar/limiter.phtml')) ?> - - <?php if ($block->isExpanded()) :?> - <?php include ($block->getTemplateFile('Magento_Catalog::product/list/toolbar/sorter.phtml')) ?> - <?php endif; ?> + <?php if ($block->getIsBottom()): ?> + <?= $block->getPagerHtml() ?> + <?= $block->fetchView($block->getTemplateFile('Magento_Catalog::product/list/toolbar/limiter.phtml')) ?> + <?php else: ?> + <?php if ($block->isExpanded()): ?> + <?= $block->fetchView($block->getTemplateFile('Magento_Catalog::product/list/toolbar/viewmode.phtml')) ?> + <?php endif ?> + <?= $block->fetchView($block->getTemplateFile('Magento_Catalog::product/list/toolbar/amount.phtml')) ?> + <?php if ($block->isExpanded()): ?> + <?= $block->fetchView($block->getTemplateFile('Magento_Catalog::product/list/toolbar/sorter.phtml')) ?> + <?php endif ?> + <?php endif ?> </div> <?php endif ?> From 3301a80f94d6f431deb0eb4c9756b922ad395ab4 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Wed, 10 Mar 2021 11:30:36 -0600 Subject: [PATCH 31/40] B2B-1701: Deprecate database media storage function - Removed the trigger error --- app/code/Magento/MediaStorage/Helper/File/Storage/Database.php | 2 +- app/code/Magento/MediaStorage/etc/adminhtml/system.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index 04896961f0c87..aae0b86e862b0 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -143,6 +143,7 @@ public function getResourceStorageModel() public function saveFile($filename) { if ($this->checkDbUsage()) { + //phpcs:ignore Magento2.Functions.DiscouragedFunction trigger_error('Database media storage function is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->saveFile($this->_removeAbsPathFromFileName($filename)); } @@ -175,7 +176,6 @@ public function renameFile($oldName, $newName) public function copyFile($oldName, $newName) { if ($this->checkDbUsage()) { - trigger_error('Database media storage function is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->copyFile( $this->_removeAbsPathFromFileName($oldName), $this->_removeAbsPathFromFileName($newName) diff --git a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml index 9c8c2c5b24398..ae825235f88ee 100644 --- a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml +++ b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml @@ -15,7 +15,7 @@ <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Storage</source_model> </field> <field id="media_database" translate="label" type="select" sortOrder="200" showInDefault="1"> - <label>Select Media Database</label> + <label>Select Media Database(Deprecated)</label> <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Database</source_model> <backend_model>Magento\MediaStorage\Model\Config\Backend\Storage\Media\Database</backend_model> <depends> From 6ef4a2ba5e98f2fff82bcb3df577f22d6b69da12 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Wed, 10 Mar 2021 11:42:18 -0600 Subject: [PATCH 32/40] B2B-1701: Deprecate database media storage function - Fixed static test errors --- app/code/Magento/MediaStorage/Helper/File/Storage/Database.php | 2 -- .../MediaStorage/Model/Config/Source/Storage/Media/Storage.php | 2 +- app/code/Magento/MediaStorage/etc/adminhtml/system.xml | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index aae0b86e862b0..61a082fc6c846 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -143,8 +143,6 @@ public function getResourceStorageModel() public function saveFile($filename) { if ($this->checkDbUsage()) { - //phpcs:ignore Magento2.Functions.DiscouragedFunction - trigger_error('Database media storage function is deprecated', E_USER_DEPRECATED); $this->getStorageDatabaseModel()->saveFile($this->_removeAbsPathFromFileName($filename)); } } diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php index 657188b82e752..3f3163f61bc67 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php @@ -27,7 +27,7 @@ public function toOptionArray() 'value' => \Magento\MediaStorage\Model\File\Storage::STORAGE_MEDIA_FILE_SYSTEM, 'label' => __('File System'), ], - ['value' => \Magento\MediaStorage\Model\File\Storage::STORAGE_MEDIA_DATABASE, 'label' => __('Database(Deprecated)')] + ['value' => \Magento\MediaStorage\Model\File\Storage::STORAGE_MEDIA_DATABASE, 'label' => __('Database (Deprecated)')] ]; } } diff --git a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml index ae825235f88ee..028243fdb71a1 100644 --- a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml +++ b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml @@ -15,7 +15,7 @@ <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Storage</source_model> </field> <field id="media_database" translate="label" type="select" sortOrder="200" showInDefault="1"> - <label>Select Media Database(Deprecated)</label> + <label>Select Media Database (Deprecated)</label> <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Database</source_model> <backend_model>Magento\MediaStorage\Model\Config\Backend\Storage\Media\Database</backend_model> <depends> From f6f929542b54bbb372f35f19428f600f6ce60398 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Thu, 11 Mar 2021 14:57:27 +0200 Subject: [PATCH 33/40] MC-41138: W3C validator reports duplicate ID on Listing Page and Search Result Page --- .../Catalog/Controller/CategoryTest.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php index 00c3133c25439..4c9f55cf3268d 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php @@ -8,14 +8,18 @@ namespace Magento\Catalog\Controller; use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Model\Category; use Magento\Catalog\Model\Category\Attribute\LayoutUpdateManager; use Magento\Catalog\Model\Product\ProductList\Toolbar as ToolbarModel; +use Magento\Catalog\Model\ResourceModel\Category\Collection; +use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; use Magento\Catalog\Model\Session; use Magento\Framework\App\Http\Context; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Registry; use Magento\Framework\View\LayoutInterface; +use Magento\Store\Model\Store; use Magento\TestFramework\Catalog\Model\CategoryLayoutUpdateManager; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\AbstractController; @@ -53,6 +57,11 @@ class CategoryTest extends AbstractController */ private $httpContext; + /** + * @var CollectionFactory + */ + private $categoryCollectionFactory; + /** * @inheritdoc */ @@ -64,6 +73,8 @@ protected function setUp(): void $this->objectManager->configure([ 'preferences' => [LayoutUpdateManager::class => CategoryLayoutUpdateManager::class] ]); + + $this->categoryCollectionFactory = $this->objectManager->create(CollectionFactory::class); $this->registry = $this->objectManager->get(Registry::class); $this->layout = $this->objectManager->get(LayoutInterface::class); $this->session = $this->objectManager->get(Session::class); @@ -233,4 +244,50 @@ public function testViewWithRememberPaginationAndPreviousValue(): void $this->assertEquals($newPaginationValue, $this->session->getData(ToolbarModel::LIMIT_PARAM_NAME)); $this->assertEquals($newPaginationValue, $this->httpContext->getValue(ToolbarModel::LIMIT_PARAM_NAME)); } + + /** + * Test to generate category page without duplicate html element ids + * + * @magentoDataFixture Magento/Catalog/_files/category_with_three_products.php + * @magentoDataFixture Magento/Catalog/_files/catalog_category_product_reindex_all.php + * @magentoDataFixture Magento/Catalog/_files/catalog_product_category_reindex_all.php + * @magentoDbIsolation disabled + */ + public function testViewWithoutDuplicateHmlElementIds(): void + { + $category = $this->loadCategory('Category 999', Store::DEFAULT_STORE_ID); + $this->dispatch('catalog/category/view/id/' . $category->getId()); + + $responseHtml = $this->getResponse()->getBody(); + $htmlElementIds = ['modes-label', 'mode-list', 'toolbar-amount', 'sorter', 'limiter']; + foreach ($htmlElementIds as $elementId) { + $matches = []; + $idAttribute = "id=\"$elementId\""; + preg_match_all("/$idAttribute/mx", $responseHtml, $matches); + $this->assertCount(1, $matches[0]); + $this->assertEquals($idAttribute, $matches[0][0]); + } + } + + /** + * Loads category by id + * + * @param string $categoryName + * @param int $storeId + * @return CategoryInterface + */ + protected function loadCategory(string $categoryName, int $storeId): CategoryInterface + { + /** @var Collection $categoryCollection */ + $categoryCollection = $this->categoryCollectionFactory->create(); + /** @var CategoryInterface $category */ + $category = $categoryCollection->setStoreId($storeId) + ->addAttributeToSelect('display_mode', 'left') + ->addAttributeToFilter(CategoryInterface::KEY_NAME, $categoryName) + ->setPageSize(1) + ->getFirstItem(); + $category->setStoreId($storeId); + + return $category; + } } From 0e92df509333b941dd257c8a2f84b9b4ac398f20 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Thu, 11 Mar 2021 15:59:16 +0200 Subject: [PATCH 34/40] MC-41138: W3C validator reports duplicate ID on Listing Page and Search Result Page --- .../testsuite/Magento/Catalog/Controller/CategoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php index 4c9f55cf3268d..36bca76b28de1 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php @@ -276,7 +276,7 @@ public function testViewWithoutDuplicateHmlElementIds(): void * @param int $storeId * @return CategoryInterface */ - protected function loadCategory(string $categoryName, int $storeId): CategoryInterface + private function loadCategory(string $categoryName, int $storeId): CategoryInterface { /** @var Collection $categoryCollection */ $categoryCollection = $this->categoryCollectionFactory->create(); From 8b76bf9f4eca450d4c52159a0d3a2bf53dae13f0 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Thu, 11 Mar 2021 10:47:28 -0600 Subject: [PATCH 35/40] B2B-1701: Deprecate database media storage function - Fixed review comments --- .../Magento/MediaStorage/Helper/File/Storage/Database.php | 2 +- .../Model/Config/Backend/Storage/Media/Database.php | 2 +- .../Model/Config/Source/Storage/Media/Database.php | 2 +- .../Model/Config/Source/Storage/Media/Storage.php | 4 ---- app/code/Magento/MediaStorage/Model/File/Storage/Database.php | 2 +- .../Model/File/Storage/Database/AbstractDatabase.php | 2 +- .../MediaStorage/Model/File/Storage/Directory/Database.php | 2 +- .../Model/ResourceModel/File/Storage/AbstractStorage.php | 2 +- .../Model/ResourceModel/File/Storage/Database.php | 2 +- .../Model/ResourceModel/File/Storage/Directory/Database.php | 2 +- 10 files changed, 9 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index 61a082fc6c846..e9823720a2166 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -15,7 +15,7 @@ * @api * @since 100.0.2 * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated * */ class Database extends \Magento\Framework\App\Helper\AbstractHelper diff --git a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php index 131777c9beb94..865af7039cd7f 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php @@ -5,7 +5,7 @@ */ namespace Magento\MediaStorage\Model\Config\Backend\Storage\Media; /** -* @deprecated Database Media storage is deprecated +* @deprecated Database MediaStorage is deprecated **/ class Database extends \Magento\Framework\App\Config\Value { diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php index 1d1e98299ee23..565c79aa26917 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php @@ -13,7 +13,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; /** - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated **/ class Database implements \Magento\Framework\Option\ArrayInterface { diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php index 3f3163f61bc67..c881b59c5c593 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Storage.php @@ -9,10 +9,6 @@ */ namespace Magento\MediaStorage\Model\Config\Source\Storage\Media; - -/** - * @deprecated Database Media storage is deprecated - **/ class Storage implements \Magento\Framework\Option\ArrayInterface { /** diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php index c11d54523544d..304ac9f0d766c 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php @@ -11,7 +11,7 @@ * @api * @since 100.0.2 * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated */ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase { diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php index 34628718fddae..9ffe8a4ed9871 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php @@ -8,7 +8,7 @@ /** * Class AbstractDatabase * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated * **/ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php index 96db61a6398f3..114534ba08c0c 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php @@ -12,7 +12,7 @@ * @api * @since 100.0.2 * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated */ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php index 81cbc44fcf326..3d6d2e851d877 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php @@ -8,7 +8,7 @@ /** * Class AbstractStorage * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated */ abstract class AbstractStorage extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php index 1fa593d7c832a..b66edf821cdb5 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php @@ -11,7 +11,7 @@ * @api * @since 100.0.2 * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated */ class Database extends \Magento\MediaStorage\Model\ResourceModel\File\Storage\AbstractStorage { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php index 6ff011d25d802..1d9e38279ed91 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php @@ -8,7 +8,7 @@ /** * Class Database * - * @deprecated Database Media storage is deprecated + * @deprecated Database MediaStorage is deprecated */ class Database extends \Magento\MediaStorage\Model\ResourceModel\File\Storage\AbstractStorage { From 632d196d4354fb767c9b00851b76899ceb48282a Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Thu, 11 Mar 2021 11:17:19 -0600 Subject: [PATCH 36/40] B2B-1701: Deprecate database media storage function - Fixed space on comments --- app/code/Magento/MediaStorage/Helper/File/Storage/Database.php | 2 +- .../Model/Config/Backend/Storage/Media/Database.php | 2 +- .../MediaStorage/Model/Config/Source/Storage/Media/Database.php | 2 +- app/code/Magento/MediaStorage/Model/File/Storage/Database.php | 2 +- .../Model/File/Storage/Database/AbstractDatabase.php | 2 +- .../Model/ResourceModel/File/Storage/AbstractStorage.php | 2 +- .../MediaStorage/Model/ResourceModel/File/Storage/Database.php | 2 +- .../Model/ResourceModel/File/Storage/Directory/Database.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index e9823720a2166..e0f5509830a0c 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -15,7 +15,7 @@ * @api * @since 100.0.2 * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated * */ class Database extends \Magento\Framework\App\Helper\AbstractHelper diff --git a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php index 865af7039cd7f..81e6c5e028be1 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php @@ -5,7 +5,7 @@ */ namespace Magento\MediaStorage\Model\Config\Backend\Storage\Media; /** -* @deprecated Database MediaStorage is deprecated +* @deprecated Database Media Storage is deprecated **/ class Database extends \Magento\Framework\App\Config\Value { diff --git a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php index 565c79aa26917..97f161e4c49d8 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Source/Storage/Media/Database.php @@ -13,7 +13,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; /** - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated **/ class Database implements \Magento\Framework\Option\ArrayInterface { diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php index 304ac9f0d766c..571dad7f0ae9a 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php @@ -11,7 +11,7 @@ * @api * @since 100.0.2 * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated */ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase { diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php index 9ffe8a4ed9871..3528ca5743ff7 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php @@ -8,7 +8,7 @@ /** * Class AbstractDatabase * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated * **/ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php index 3d6d2e851d877..0533c0229ea3d 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/AbstractStorage.php @@ -8,7 +8,7 @@ /** * Class AbstractStorage * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated */ abstract class AbstractStorage extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php index b66edf821cdb5..863b368883fbe 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Database.php @@ -11,7 +11,7 @@ * @api * @since 100.0.2 * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated */ class Database extends \Magento\MediaStorage\Model\ResourceModel\File\Storage\AbstractStorage { diff --git a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php index 1d9e38279ed91..342761646e396 100644 --- a/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/ResourceModel/File/Storage/Directory/Database.php @@ -8,7 +8,7 @@ /** * Class Database * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated */ class Database extends \Magento\MediaStorage\Model\ResourceModel\File\Storage\AbstractStorage { From 4fc396a18ee01a697a637c09412a682632936c2d Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Thu, 11 Mar 2021 11:18:26 -0600 Subject: [PATCH 37/40] B2B-1701: Deprecate database media storage function - Fixed space on comments on missed dir file --- .../MediaStorage/Model/File/Storage/Directory/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php index 114534ba08c0c..03d5eee617b1b 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php @@ -12,7 +12,7 @@ * @api * @since 100.0.2 * - * @deprecated Database MediaStorage is deprecated + * @deprecated Database Media Storage is deprecated */ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase { From abdeb4e7729d8dfea6cb94b772c7ffbb75e52c7f Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 12 Mar 2021 07:43:08 -0600 Subject: [PATCH 38/40] B2B-1701: Deprecate database media storage function - Added test new changes --- .../Magento/MediaStorage/Helper/File/Storage/Database.php | 1 + .../Test/Unit/Helper/File/Storage/DatabaseTest.php | 6 ++++++ app/code/Magento/MediaStorage/etc/adminhtml/system.xml | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index e0f5509830a0c..ce5d9cf36002d 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -8,6 +8,7 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; +trigger_error('Class is deprecated', E_USER_DEPRECATED); /** * Database saving file helper diff --git a/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php b/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php index 0a7038838cf97..fed116e6db1a1 100644 --- a/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php +++ b/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php @@ -49,6 +49,7 @@ class DatabaseTest extends TestCase protected function setUp(): void { + set_error_handler(null); $this->dbStorageFactoryMock = $this->getMockBuilder( DatabaseFactory::class )->disableOriginalConstructor() @@ -519,4 +520,9 @@ public function testGetMediaBaseDir() $this->assertEquals('media-dir', $this->helper->getMediaBaseDir()); $this->assertEquals('media-dir', $this->helper->getMediaBaseDir()); } + + protected function tearDown(): void + { + restore_error_handler(); + } } diff --git a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml index 028243fdb71a1..9c8c2c5b24398 100644 --- a/app/code/Magento/MediaStorage/etc/adminhtml/system.xml +++ b/app/code/Magento/MediaStorage/etc/adminhtml/system.xml @@ -15,7 +15,7 @@ <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Storage</source_model> </field> <field id="media_database" translate="label" type="select" sortOrder="200" showInDefault="1"> - <label>Select Media Database (Deprecated)</label> + <label>Select Media Database</label> <source_model>Magento\MediaStorage\Model\Config\Source\Storage\Media\Database</source_model> <backend_model>Magento\MediaStorage\Model\Config\Backend\Storage\Media\Database</backend_model> <depends> From 313d1eefab33d32761dc354882bb2fe38865974d Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 12 Mar 2021 08:38:43 -0600 Subject: [PATCH 39/40] B2B-1701: Deprecate database media storage function - removed trigger error on db file --- app/code/Magento/MediaStorage/Helper/File/Storage/Database.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php index ce5d9cf36002d..e0f5509830a0c 100644 --- a/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Helper/File/Storage/Database.php @@ -8,7 +8,6 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; -trigger_error('Class is deprecated', E_USER_DEPRECATED); /** * Database saving file helper From 4f7121ebd0b3fc3a281b33c2c0e11341d4284cf3 Mon Sep 17 00:00:00 2001 From: Anusha Vattam <avattam@adobe.com> Date: Fri, 12 Mar 2021 11:27:31 -0600 Subject: [PATCH 40/40] B2B-1701: Deprecate database media storage function - removed test changes as not required --- .../Test/Unit/Helper/File/Storage/DatabaseTest.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php b/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php index fed116e6db1a1..0a7038838cf97 100644 --- a/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php +++ b/app/code/Magento/MediaStorage/Test/Unit/Helper/File/Storage/DatabaseTest.php @@ -49,7 +49,6 @@ class DatabaseTest extends TestCase protected function setUp(): void { - set_error_handler(null); $this->dbStorageFactoryMock = $this->getMockBuilder( DatabaseFactory::class )->disableOriginalConstructor() @@ -520,9 +519,4 @@ public function testGetMediaBaseDir() $this->assertEquals('media-dir', $this->helper->getMediaBaseDir()); $this->assertEquals('media-dir', $this->helper->getMediaBaseDir()); } - - protected function tearDown(): void - { - restore_error_handler(); - } }