Skip to content

Commit ad9212f

Browse files
author
Serhiy Zhovnir
committed
Merge branch '2.3-develop' of github.com:magento/magento2 into issue-22786-fix-validation-for-UPS-configurations
2 parents 9fc3247 + 72aebb7 commit ad9212f

File tree

138 files changed

+5119
-150
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+5119
-150
lines changed

app/code/Magento/Catalog/Model/Product/Option/Type/Select.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
/**
1212
* Catalog product option select type
13+
*
14+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
1315
*/
1416
class Select extends \Magento\Catalog\Model\Product\Option\Type\DefaultType
1517
{
@@ -30,23 +32,35 @@ class Select extends \Magento\Catalog\Model\Product\Option\Type\DefaultType
3032
*/
3133
protected $string;
3234

35+
/**
36+
* @var array
37+
*/
38+
private $singleSelectionTypes;
39+
3340
/**
3441
* @param \Magento\Checkout\Model\Session $checkoutSession
3542
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
3643
* @param \Magento\Framework\Stdlib\StringUtils $string
3744
* @param \Magento\Framework\Escaper $escaper
3845
* @param array $data
46+
* @param array $singleSelectionTypes
3947
*/
4048
public function __construct(
4149
\Magento\Checkout\Model\Session $checkoutSession,
4250
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
4351
\Magento\Framework\Stdlib\StringUtils $string,
4452
\Magento\Framework\Escaper $escaper,
45-
array $data = []
53+
array $data = [],
54+
array $singleSelectionTypes = []
4655
) {
4756
$this->string = $string;
4857
$this->_escaper = $escaper;
4958
parent::__construct($checkoutSession, $scopeConfig, $data);
59+
60+
$this->singleSelectionTypes = $singleSelectionTypes ?: [
61+
'drop_down' => \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN,
62+
'radio' => \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO,
63+
];
5064
}
5165

5266
/**
@@ -310,10 +324,6 @@ public function getOptionSku($optionValue, $skuDelimiter)
310324
*/
311325
protected function _isSingleSelection()
312326
{
313-
$single = [
314-
\Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN,
315-
\Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO,
316-
];
317-
return in_array($this->getOption()->getType(), $single);
327+
return in_array($this->getOption()->getType(), $this->singleSelectionTypes, true);
318328
}
319329
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
-->
7+
8+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
9+
<actionGroup name="StorefrontAssertProductSpecialPriceOnProductPageActionGroup">
10+
<arguments>
11+
<argument name="product" type="entity"/>
12+
<argument name="specialPrice" type="string"/>
13+
</arguments>
14+
<amOnPage url="{{StorefrontProductPage.url(product.name)}}" stepKey="onFirstProductPage"/>
15+
<waitForPageLoad stepKey="waitForFirstProductPage"/>
16+
<grabTextFrom selector="{{StorefrontProductInfoMainSection.specialPriceValue}}" stepKey="grabProductSpecialPrice"/>
17+
<assertEquals actual="$grabProductSpecialPrice" expectedType="string" expected="{{specialPrice}}" stepKey="assertProductPriceValuesAreEqual"/>
18+
</actionGroup>
19+
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontProductPageActionGroup.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
<see selector="{{StorefrontMessagesSection.success}}" userInput="You added {{productName}} to your shopping cart." stepKey="seeAddToCartSuccessMessage"/>
2020
</actionGroup>
2121

22+
<actionGroup name="AddProductWithQtyToCartFromStorefrontProductPage" extends="addToCartFromStorefrontProductPage">
23+
<arguments>
24+
<argument name="productName" type="string"/>
25+
<argument name="productQty" type="string"/>
26+
</arguments>
27+
<fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="{{productQty}}" stepKey="fillProductQuantity" before="addToCart"/>
28+
</actionGroup>
29+
2230
<!--Verify text length validation hint with multiple inputs-->
2331
<actionGroup name="testDynamicValidationHint">
2432
<arguments>

app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,11 @@
481481
<var key="sku" entityType="product" entityKey="sku" />
482482
<requiredEntity type="product_option">ProductOptionValueDropdown</requiredEntity>
483483
</entity>
484+
<entity name="productWithDropdownAndFieldOptions" type="product">
485+
<var key="sku" entityType="product" entityKey="sku" />
486+
<requiredEntity type="product_option">ProductOptionValueDropdown</requiredEntity>
487+
<requiredEntity type="product_option">ProductOptionField</requiredEntity>
488+
</entity>
484489
<entity name="ProductWithTextFieldAndAreaOptions" type="product">
485490
<var key="sku" entityType="product" entityKey="sku" />
486491
<requiredEntity type="product_option">ProductOptionField</requiredEntity>
@@ -1069,4 +1074,74 @@
10691074
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
10701075
<requiredEntity type="custom_attribute_array">ApiProductDescription</requiredEntity>
10711076
</entity>
1077+
<entity name="SimpleProductWithSpecialPrice" type="product">
1078+
<data key="sku" unique="suffix">SimpleProductWithSpecialPrice</data>
1079+
<data key="type_id">simple</data>
1080+
<data key="attribute_set_id">4</data>
1081+
<data key="name" unique="suffix">SimpleProduct</data>
1082+
<data key="price">100.00</data>
1083+
<data key="special_price">90.00</data>
1084+
<data key="visibility">4</data>
1085+
<data key="status">1</data>
1086+
<data key="quantity">86</data>
1087+
<data key="urlKey" unique="suffix">simpleproduct</data>
1088+
<data key="weight">1</data>
1089+
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
1090+
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
1091+
</entity>
1092+
<entity name="SimpleProductWithSpecialPriceSecond" type="product">
1093+
<data key="sku" unique="suffix">SimpleProductWithSpecialPriceSecond</data>
1094+
<data key="type_id">simple</data>
1095+
<data key="attribute_set_id">4</data>
1096+
<data key="name" unique="suffix">SimpleProduct</data>
1097+
<data key="price">150.00</data>
1098+
<data key="special_price">110.00</data>
1099+
<data key="visibility">4</data>
1100+
<data key="status">1</data>
1101+
<data key="quantity">86</data>
1102+
<data key="urlKey" unique="suffix">simpleproduct</data>
1103+
<data key="weight">1</data>
1104+
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
1105+
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
1106+
</entity>
1107+
<entity name="SimpleProduct_100" type="product">
1108+
<data key="sku" unique="suffix">testSku</data>
1109+
<data key="type_id">simple</data>
1110+
<data key="attribute_set_id">4</data>
1111+
<data key="visibility">4</data>
1112+
<data key="name" unique="suffix">testProductName</data>
1113+
<data key="price">100.00</data>
1114+
<data key="urlKey" unique="suffix">testurlkey</data>
1115+
<data key="status">1</data>
1116+
<data key="quantity">777</data>
1117+
<data key="weight">1</data>
1118+
<requiredEntity type="product_extension_attribute">EavStock777</requiredEntity>
1119+
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
1120+
</entity>
1121+
<entity name="ApiSimpleOneQty10" type="product2">
1122+
<data key="sku" unique="suffix">api-simple-product</data>
1123+
<data key="type_id">simple</data>
1124+
<data key="attribute_set_id">4</data>
1125+
<data key="visibility">4</data>
1126+
<data key="name" unique="suffix">Api Simple Product</data>
1127+
<data key="price">40.00</data>
1128+
<data key="urlKey" unique="suffix">api-simple-product</data>
1129+
<data key="status">1</data>
1130+
<data key="quantity">10</data>
1131+
<requiredEntity type="product_extension_attribute">EavStock10</requiredEntity>
1132+
<requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity>
1133+
</entity>
1134+
<entity name="ApiSimpleTwoQty10" type="product2">
1135+
<data key="sku" unique="suffix">api-simple-product-two</data>
1136+
<data key="type_id">simple</data>
1137+
<data key="attribute_set_id">4</data>
1138+
<data key="visibility">4</data>
1139+
<data key="name" unique="suffix">Api Simple Product Two</data>
1140+
<data key="price">40.00</data>
1141+
<data key="urlKey" unique="suffix">api-simple-product-two</data>
1142+
<data key="status">1</data>
1143+
<data key="quantity">10</data>
1144+
<requiredEntity type="product_extension_attribute">EavStock10</requiredEntity>
1145+
<requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity>
1146+
</entity>
10721147
</entities>

app/code/Magento/Catalog/Test/Mftf/Data/ProductExtensionAttributeData.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@
2020
<entity name="EavStock1" type="product_extension_attribute">
2121
<requiredEntity type="stock_item">Qty_1</requiredEntity>
2222
</entity>
23+
<entity name="EavStock777" type="product_extension_attribute">
24+
<requiredEntity type="stock_item">Qty_777</requiredEntity>
25+
</entity>
2326
</entities>

app/code/Magento/Catalog/Test/Mftf/Data/StockItemData.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@
3232
<data key="qty">1</data>
3333
<data key="is_in_stock">true</data>
3434
</entity>
35+
<entity name="Qty_777" type="stock_item">
36+
<data key="qty">777</data>
37+
<data key="is_in_stock">true</data>
38+
</entity>
3539
</entities>

app/code/Magento/Catalog/etc/di.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,4 +1165,12 @@
11651165
</argument>
11661166
</arguments>
11671167
</type>
1168+
<type name="Magento\Catalog\Model\Product\Option\Type\Select">
1169+
<arguments>
1170+
<argument name="singleSelectionTypes" xsi:type="array">
1171+
<item name="drop_down" xsi:type="const">Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN</item>
1172+
<item name="radio" xsi:type="const">Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO</item>
1173+
</argument>
1174+
</arguments>
1175+
</type>
11681176
</config>

app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77

88
namespace Magento\CatalogGraphQl\Model\Resolver;
99

10-
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
10+
use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector;
1111
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Deferred\Product as ProductDataProvider;
1212
use Magento\Framework\GraphQl\Config\Element\Field;
1313
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14-
use Magento\Framework\GraphQl\Query\FieldTranslator;
15-
use Magento\Framework\GraphQl\Query\Resolver\Value;
1614
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
1715
use Magento\Framework\GraphQl\Query\ResolverInterface;
16+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1817

1918
/**
2019
* @inheritdoc
@@ -32,23 +31,23 @@ class Product implements ResolverInterface
3231
private $valueFactory;
3332

3433
/**
35-
* @var FieldTranslator
34+
* @var ProductFieldsSelector
3635
*/
37-
private $fieldTranslator;
36+
private $productFieldsSelector;
3837

3938
/**
4039
* @param ProductDataProvider $productDataProvider
4140
* @param ValueFactory $valueFactory
42-
* @param FieldTranslator $fieldTranslator
41+
* @param ProductFieldsSelector $productFieldsSelector
4342
*/
4443
public function __construct(
4544
ProductDataProvider $productDataProvider,
4645
ValueFactory $valueFactory,
47-
FieldTranslator $fieldTranslator
46+
ProductFieldsSelector $productFieldsSelector
4847
) {
4948
$this->productDataProvider = $productDataProvider;
5049
$this->valueFactory = $valueFactory;
51-
$this->fieldTranslator = $fieldTranslator;
50+
$this->productFieldsSelector = $productFieldsSelector;
5251
}
5352

5453
/**
@@ -60,7 +59,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
6059
throw new GraphQlInputException(__('No child sku found for product link.'));
6160
}
6261
$this->productDataProvider->addProductSku($value['sku']);
63-
$fields = $this->getProductFields($info);
62+
$fields = $this->productFieldsSelector->getProductFieldsFromInfo($info);
6463
$this->productDataProvider->addEavAttributes($fields);
6564

6665
$result = function () use ($value) {
@@ -86,34 +85,4 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
8685

8786
return $this->valueFactory->create($result);
8887
}
89-
90-
/**
91-
* Return field names for all requested product fields.
92-
*
93-
* @param ResolveInfo $info
94-
* @return string[]
95-
*/
96-
private function getProductFields(ResolveInfo $info) : array
97-
{
98-
$fieldNames = [];
99-
foreach ($info->fieldNodes as $node) {
100-
if ($node->name->value !== 'product') {
101-
continue;
102-
}
103-
foreach ($node->selectionSet->selections as $selectionNode) {
104-
if ($selectionNode->kind === 'InlineFragment') {
105-
foreach ($selectionNode->selectionSet->selections as $inlineSelection) {
106-
if ($inlineSelection->kind === 'InlineFragment') {
107-
continue;
108-
}
109-
$fieldNames[] = $this->fieldTranslator->translate($inlineSelection->name->value);
110-
}
111-
continue;
112-
}
113-
$fieldNames[] = $this->fieldTranslator->translate($selectionNode->name->value);
114-
}
115-
}
116-
117-
return $fieldNames;
118-
}
11988
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogGraphQl\Model\Resolver\Product;
9+
10+
use Magento\Framework\GraphQl\Query\FieldTranslator;
11+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
12+
13+
/**
14+
* Select Product Fields From Resolve Info
15+
*/
16+
class ProductFieldsSelector
17+
{
18+
/**
19+
* @var FieldTranslator
20+
*/
21+
private $fieldTranslator;
22+
23+
/**
24+
* @param FieldTranslator $fieldTranslator
25+
*/
26+
public function __construct(FieldTranslator $fieldTranslator)
27+
{
28+
$this->fieldTranslator = $fieldTranslator;
29+
}
30+
31+
/**
32+
* Return field names for all requested product fields.
33+
*
34+
* @param ResolveInfo $info
35+
* @param string $productNodeName
36+
* @return string[]
37+
*/
38+
public function getProductFieldsFromInfo(ResolveInfo $info, string $productNodeName = 'product') : array
39+
{
40+
$fieldNames = [];
41+
foreach ($info->fieldNodes as $node) {
42+
if ($node->name->value !== $productNodeName) {
43+
continue;
44+
}
45+
foreach ($node->selectionSet->selections as $selectionNode) {
46+
if ($selectionNode->kind === 'InlineFragment') {
47+
foreach ($selectionNode->selectionSet->selections as $inlineSelection) {
48+
if ($inlineSelection->kind === 'InlineFragment') {
49+
continue;
50+
}
51+
$fieldNames[] = $this->fieldTranslator->translate($inlineSelection->name->value);
52+
}
53+
continue;
54+
}
55+
$fieldNames[] = $this->fieldTranslator->translate($selectionNode->name->value);
56+
}
57+
}
58+
59+
return $fieldNames;
60+
}
61+
}

app/code/Magento/CatalogGraphQl/etc/graphql/di.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,19 @@
8080
</virtualType>
8181
<preference for="Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match"
8282
type="Magento\CatalogGraphQl\Model\Search\Adapter\Mysql\Query\Builder\Match" />
83+
<type name="Magento\StoreGraphQl\Model\Resolver\Store\StoreConfigDataProvider">
84+
<arguments>
85+
<argument name="extendedConfigData" xsi:type="array">
86+
<item name="product_url_suffix" xsi:type="string">catalog/seo/product_url_suffix</item>
87+
<item name="category_url_suffix" xsi:type="string">catalog/seo/category_url_suffix</item>
88+
<item name="title_separator" xsi:type="string">catalog/seo/title_separator</item>
89+
<item name="list_mode" xsi:type="string">catalog/frontend/list_mode</item>
90+
<item name="grid_per_page_values" xsi:type="string">catalog/frontend/grid_per_page_values</item>
91+
<item name="list_per_page_values" xsi:type="string">catalog/frontend/list_per_page_values</item>
92+
<item name="grid_per_page" xsi:type="string">catalog/frontend/grid_per_page</item>
93+
<item name="list_per_page" xsi:type="string">catalog/frontend/list_per_page</item>
94+
<item name="catalog_default_sort_by" xsi:type="string">catalog/frontend/default_sort_by</item>
95+
</argument>
96+
</arguments>
97+
</type>
8398
</config>

app/code/Magento/CatalogGraphQl/etc/schema.graphqls

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,15 @@ type SortFields @doc(description: "SortFields contains a default value for sort
401401
default: String @doc(description: "Default value of sort fields")
402402
options: [SortField] @doc(description: "Available sort fields")
403403
}
404+
405+
type StoreConfig @doc(description: "The type contains information about a store config") {
406+
product_url_suffix : String @doc(description: "Product URL Suffix")
407+
category_url_suffix : String @doc(description: "Category URL Suffix")
408+
title_separator : String @doc(description: "Page Title Separator")
409+
list_mode : String @doc(description: "List Mode")
410+
grid_per_page_values : String @doc(description: "Products per Page on Grid Allowed Values")
411+
list_per_page_values : String @doc(description: "Products per Page on List Allowed Values")
412+
grid_per_page : Int @doc(description: "Products per Page on Grid Default Value")
413+
list_per_page : Int @doc(description: "Products per Page on List Default Value")
414+
catalog_default_sort_by : String @doc(description: "Default Sort By")
415+
}

0 commit comments

Comments
 (0)