Skip to content

Commit 88ebc57

Browse files
committed
Merge branch '2.4-develop' into MC-31481
2 parents c94087e + 9f093a3 commit 88ebc57

File tree

193 files changed

+6911
-1330
lines changed

Some content is hidden

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

193 files changed

+6911
-1330
lines changed

app/code/Magento/Bundle/Test/Mftf/Test/StorefrontSortBundleProductsByPriceTest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@
109109
<deleteData createDataKey="createFirstProductForBundle" stepKey="deleteFirstProductForBundle"/>
110110
<deleteData createDataKey="createSecondProductForBundle" stepKey="deleteSecondProductForBundle"/>
111111
<deleteData createDataKey="createThirdBundleProduct" stepKey="deleteThirdBundleProduct"/>
112+
113+
<!-- Reindex invalidated indices after product attribute has been created/deleted -->
114+
<actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/>
112115
</after>
113116

114117
<!-- Open created category on Storefront -->

app/code/Magento/Catalog/Block/Product/ImageFactory.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ private function getLabel(Product $product, string $imageType): string
123123
if (empty($label)) {
124124
$label = $product->getName();
125125
}
126-
return (string) $label;
126+
return (string)$label;
127127
}
128128

129129
/**
@@ -161,15 +161,15 @@ public function create(Product $product, string $imageId, array $attributes = nu
161161
}
162162

163163
$attributes = $attributes === null ? [] : $attributes;
164-
164+
165165
$data = [
166166
'data' => [
167167
'template' => 'Magento_Catalog::product/image_with_borders.phtml',
168168
'image_url' => $imageAsset->getUrl(),
169169
'width' => $imageMiscParams['image_width'],
170170
'height' => $imageMiscParams['image_height'],
171171
'label' => $this->getLabel($product, $imageMiscParams['image_type']),
172-
'ratio' => $this->getRatio($imageMiscParams['image_width'], $imageMiscParams['image_height']),
172+
'ratio' => $this->getRatio($imageMiscParams['image_width'] ?? 0, $imageMiscParams['image_height'] ?? 0),
173173
'custom_attributes' => $this->getStringCustomAttributes($attributes),
174174
'class' => $this->getClass($attributes),
175175
'product_id' => $product->getId()

app/code/Magento/Catalog/Model/Product.php

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Catalog\Api\Data\ProductInterface;
1111
use Magento\Catalog\Api\ProductLinkRepositoryInterface;
1212
use Magento\Catalog\Model\Product\Attribute\Backend\Media\EntryConverterPool;
13+
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
1314
use Magento\Catalog\Model\FilterProductCustomAttribute;
1415
use Magento\Framework\Api\AttributeValueFactory;
1516
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -108,7 +109,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements
108109
/**
109110
* Product object customization (not stored in DB)
110111
*
111-
* @var array
112+
* @var OptionInterface[]
112113
*/
113114
protected $_customOptions = [];
114115

@@ -2062,7 +2063,7 @@ public function addCustomOption($code, $value, $product = null)
20622063
/**
20632064
* Sets custom options for the product
20642065
*
2065-
* @param array $options Array of options
2066+
* @param OptionInterface[] $options Array of options
20662067
* @return void
20672068
*/
20682069
public function setCustomOptions(array $options)
@@ -2073,7 +2074,7 @@ public function setCustomOptions(array $options)
20732074
/**
20742075
* Get all custom options of the product
20752076
*
2076-
* @return array
2077+
* @return OptionInterface[]
20772078
*/
20782079
public function getCustomOptions()
20792080
{
@@ -2084,14 +2085,11 @@ public function getCustomOptions()
20842085
* Get product custom option info
20852086
*
20862087
* @param string $code
2087-
* @return array
2088+
* @return OptionInterface|null
20882089
*/
20892090
public function getCustomOption($code)
20902091
{
2091-
if (isset($this->_customOptions[$code])) {
2092-
return $this->_customOptions[$code];
2093-
}
2094-
return null;
2092+
return $this->_customOptions[$code] ?? null;
20952093
}
20962094

20972095
/**
@@ -2101,11 +2099,7 @@ public function getCustomOption($code)
21012099
*/
21022100
public function hasCustomOptions()
21032101
{
2104-
if (count($this->_customOptions)) {
2105-
return true;
2106-
} else {
2107-
return false;
2108-
}
2102+
return (bool)count($this->_customOptions);
21092103
}
21102104

21112105
/**
@@ -2405,16 +2399,14 @@ public function reloadPriceInfo()
24052399
}
24062400
}
24072401

2408-
// phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames
24092402
/**
24102403
* Return Data Object data in array format.
24112404
*
24122405
* @return array
24132406
* @todo refactor with converter for AbstractExtensibleModel
24142407
*/
2415-
public function __toArray()
2408+
public function __toArray() //phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames
24162409
{
2417-
// phpcs:enable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames
24182410
$data = $this->_data;
24192411
$hasToArray = function ($model) {
24202412
return is_object($model) && method_exists($model, '__toArray') && is_callable([$model, '__toArray']);

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

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,37 @@
66
namespace Magento\Catalog\Model\Product;
77

88
use Magento\Catalog\Model\Product;
9+
use Magento\Catalog\Model\Product\Type\Pool;
10+
use Magento\Catalog\Model\Product\Type\Price;
11+
use Magento\Catalog\Model\Product\Type\Price\Factory as PriceFactory;
12+
use Magento\Catalog\Model\Product\Type\Simple;
13+
use Magento\Catalog\Model\ProductTypes\ConfigInterface;
914
use Magento\Framework\Data\OptionSourceInterface;
15+
use Magento\Framework\Pricing\PriceInfo\Factory as PriceInfoFactory;
1016

1117
/**
1218
* Product type model
1319
*
20+
*
1421
* @api
1522
* @since 100.0.2
1623
*/
1724
class Type implements OptionSourceInterface
1825
{
19-
/**#@+
20-
* Available product types
21-
*/
2226
const TYPE_SIMPLE = 'simple';
2327

2428
const TYPE_BUNDLE = 'bundle';
2529

2630
const TYPE_VIRTUAL = 'virtual';
27-
/**#@-*/
2831

29-
/**
30-
* Default product type
31-
*/
3232
const DEFAULT_TYPE = 'simple';
3333

34-
/**
35-
* Default product type model
36-
*/
37-
const DEFAULT_TYPE_MODEL = \Magento\Catalog\Model\Product\Type\Simple::class;
34+
const DEFAULT_TYPE_MODEL = Simple::class;
3835

39-
/**
40-
* Default price model
41-
*/
42-
const DEFAULT_PRICE_MODEL = \Magento\Catalog\Model\Product\Type\Price::class;
36+
const DEFAULT_PRICE_MODEL = Price::class;
4337

4438
/**
45-
* @var \Magento\Catalog\Model\ProductTypes\ConfigInterface
39+
* @var ConfigInterface
4640
*/
4741
protected $_config;
4842

@@ -77,35 +71,35 @@ class Type implements OptionSourceInterface
7771
/**
7872
* Product type factory
7973
*
80-
* @var \Magento\Catalog\Model\Product\Type\Pool
74+
* @var Pool
8175
*/
8276
protected $_productTypePool;
8377

8478
/**
8579
* Price model factory
8680
*
87-
* @var \Magento\Catalog\Model\Product\Type\Price\Factory
81+
* @var PriceFactory
8882
*/
8983
protected $_priceFactory;
9084

9185
/**
92-
* @var \Magento\Framework\Pricing\PriceInfo\Factory
86+
* @var PriceInfoFactory
9387
*/
9488
protected $_priceInfoFactory;
9589

9690
/**
9791
* Construct
9892
*
99-
* @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $config
100-
* @param \Magento\Catalog\Model\Product\Type\Pool $productTypePool
101-
* @param \Magento\Catalog\Model\Product\Type\Price\Factory $priceFactory
102-
* @param \Magento\Framework\Pricing\PriceInfo\Factory $priceInfoFactory
93+
* @param ConfigInterface $config
94+
* @param Pool $productTypePool
95+
* @param PriceFactory $priceFactory
96+
* @param PriceInfoFactory $priceInfoFactory
10397
*/
10498
public function __construct(
105-
\Magento\Catalog\Model\ProductTypes\ConfigInterface $config,
106-
\Magento\Catalog\Model\Product\Type\Pool $productTypePool,
107-
\Magento\Catalog\Model\Product\Type\Price\Factory $priceFactory,
108-
\Magento\Framework\Pricing\PriceInfo\Factory $priceInfoFactory
99+
ConfigInterface $config,
100+
Pool $productTypePool,
101+
PriceFactory $priceFactory,
102+
PriceInfoFactory $priceInfoFactory
109103
) {
110104
$this->_config = $config;
111105
$this->_productTypePool = $productTypePool;
@@ -116,8 +110,8 @@ public function __construct(
116110
/**
117111
* Factory to product singleton product type instances
118112
*
119-
* @param \Magento\Catalog\Model\Product $product
120-
* @return \Magento\Catalog\Model\Product\Type\AbstractType
113+
* @param \Magento\Catalog\Api\Data\ProductInterface $product
114+
* @return \Magento\Catalog\Model\Product\Type\AbstractType
121115
*/
122116
public function factory($product)
123117
{
@@ -139,8 +133,8 @@ public function factory($product)
139133
/**
140134
* Product type price model factory
141135
*
142-
* @param string $productType
143-
* @return \Magento\Catalog\Model\Product\Type\Price
136+
* @param string $productType
137+
* @return \Magento\Catalog\Model\Product\Type\Price
144138
*/
145139
public function priceFactory($productType)
146140
{
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminAddProductToCategoryActionGroup">
12+
<annotations>
13+
<description>Add Product to Category</description>
14+
</annotations>
15+
<arguments>
16+
<argument name="product"/>
17+
</arguments>
18+
19+
<scrollTo selector="{{AdminCategoryBasicFieldSection.productsInCategory}}" x="0" y="-80" stepKey="scrollToProductInCategory"/>
20+
<click selector="{{AdminCategoryBasicFieldSection.productsInCategory}}" stepKey="clickOnProductInCategory"/>
21+
<fillField selector="{{AdminCategoryContentSection.productTableColumnName}}" userInput="{{product.name}}" stepKey="selectProduct"/>
22+
<click selector="{{AdminCategoryContentSection.productSearch}}" stepKey="clickSearchButton"/>
23+
<click selector="{{AdminCategoryContentSection.productTableRow}}" stepKey="selectProductFromTableRow"/>
24+
</actionGroup>
25+
</actionGroups>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
10+
<actionGroup name="AdminSetUseInSearchValueForProductAttributeActionGroup">
11+
<annotations>
12+
<description>Set 'Use In Search' value for product attribute</description>
13+
</annotations>
14+
<arguments>
15+
<argument name="useInSearchValue" type="string" defaultValue="Yes"/>
16+
</arguments>
17+
18+
<scrollToTopOfPage stepKey="scrollToTopOfPage"/>
19+
<click selector="{{StorefrontPropertiesSection.StoreFrontPropertiesTab}}" stepKey="clickStorefrontPropertiesTab"/>
20+
<waitForElementVisible selector="{{AdvancedAttributePropertiesSection.UseInSearch}}" stepKey="waitForUseInSearchElementVisible"/>
21+
<selectOption selector="{{AdvancedAttributePropertiesSection.UseInSearch}}" userInput="{{useInSearchValue}}" stepKey="setUseInSearchValue"/>
22+
</actionGroup>
23+
</actionGroups>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
1111
<actionGroup name="AssertProductOnCategoryPageActionGroup" extends="StorefrontCheckCategorySimpleProductActionGroup">
1212
<annotations>
13-
<description>EXTENDS:StorefrontCheckCategorySimpleProduct. Removes 'AssertProductPrice', 'moveMouseOverProduct', 'AssertAddToCart'</description>
13+
<description>DEPRECATED. Use AssertStorefrontProductIsPresentOnCategoryPageActionGroup.
14+
EXTENDS:StorefrontCheckCategorySimpleProduct. Removes 'AssertProductPrice', 'moveMouseOverProduct', 'AssertAddToCart'</description>
1415
</annotations>
1516
<remove keyForRemoval="AssertProductPrice"/>
1617
<remove keyForRemoval="moveMouseOverProduct"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AssertStorefrontProductIsPresentOnCategoryPageActionGroup">
12+
<annotations>
13+
<description>Validate that the provided Product is present and has correct name on a Category page.</description>
14+
</annotations>
15+
<arguments>
16+
<argument name="productName" type="string" defaultValue="{{ApiSimpleOne.name}}"/>
17+
</arguments>
18+
19+
<waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="assertProductName"/>
20+
</actionGroup>
21+
</actionGroups>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<fillField userInput="{{simpleProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="fillSKU"/>
2525
<fillField userInput="{{simpleProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="fillPrice"/>
2626
<fillField userInput="{{simpleProduct.quantity}}" selector="{{AdminProductFormSection.productQuantity}}" stepKey="fillQuantity"/>
27+
<selectOption userInput="{{simpleProduct.visibility}}" selector="{{AdminProductFormSection.visibility}}" stepKey="fillVisibility"/>
2728
<searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[{{category.name}}]" stepKey="searchAndSelectCategory"/>
2829
<click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/>
2930
<fillField userInput="{{simpleProduct.urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/>

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@
212212
<data key="quantity">1001</data>
213213
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
214214
</entity>
215+
<entity name="SimpleProductDisabledStockQuantityZero" type="product">
216+
<data key="sku" unique="suffix">testSku</data>
217+
<data key="type_id">simple</data>
218+
<data key="attribute_set_id">4</data>
219+
<data key="name" unique="suffix">Simple Product Disabled Quantity Zero</data>
220+
<data key="price">123.00</data>
221+
<data key="visibility">4</data>
222+
<data key="status">2</data>
223+
<data key="quantity">0</data>
224+
<requiredEntity type="product_extension_attribute">EavStock0</requiredEntity>
225+
</entity>
215226
<entity name="SimpleProductNotVisibleIndividually" type="product">
216227
<data key="name" unique="suffix">Simple Product Not Visible Individually</data>
217228
<data key="sku" unique="suffix">simple_product_not_visible_individually</data>

0 commit comments

Comments
 (0)