Skip to content

Commit 98f0643

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into MC-34292
2 parents aad32db + 9772213 commit 98f0643

File tree

80 files changed

+3181
-221
lines changed

Some content is hidden

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

80 files changed

+3181
-221
lines changed

.github/stale.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Configuration for probot-stale - https://github.com/probot/stale
22

33
# Number of days of inactivity before an Issue or Pull Request becomes stale
4-
daysUntilStale: 76
4+
daysUntilStale: 76
55

66
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
77
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
@@ -18,7 +18,7 @@ exemptLabels:
1818
- "Progress: dev in progress"
1919
- "Progress: PR in progress"
2020
- "Progress: done"
21-
- "B2B: GraphQL"
21+
- "B2B: GraphQL"
2222
- "Progress: PR Created"
2323
- "PAP"
2424
- "Project: Login as Customer"
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Catalog\Model\Attribute\Backend;
10+
11+
use Magento\Catalog\Model\AbstractModel;
12+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
13+
use Magento\Eav\Model\Entity\Attribute\Backend\DefaultBackend as ParentBackend;
14+
use Magento\Eav\Model\Entity\Attribute\Exception;
15+
use Magento\Framework\DataObject;
16+
use Magento\Framework\Exception\LocalizedException;
17+
use Magento\Framework\Validation\ValidationException;
18+
use Magento\Framework\Validator\HTML\WYSIWYGValidatorInterface;
19+
20+
/**
21+
* Default backend model for catalog attributes.
22+
*/
23+
class DefaultBackend extends ParentBackend
24+
{
25+
/**
26+
* @var WYSIWYGValidatorInterface
27+
*/
28+
private $wysiwygValidator;
29+
30+
/**
31+
* @param WYSIWYGValidatorInterface $wysiwygValidator
32+
*/
33+
public function __construct(WYSIWYGValidatorInterface $wysiwygValidator)
34+
{
35+
$this->wysiwygValidator = $wysiwygValidator;
36+
}
37+
38+
/**
39+
* Validate user HTML value.
40+
*
41+
* @param DataObject $object
42+
* @return void
43+
* @throws LocalizedException
44+
*/
45+
private function validateHtml(DataObject $object): void
46+
{
47+
$attribute = $this->getAttribute();
48+
$code = $attribute->getAttributeCode();
49+
if ($attribute instanceof Attribute && $attribute->getIsHtmlAllowedOnFront()) {
50+
$value = $object->getData($code);
51+
if ($value
52+
&& is_string($value)
53+
&& (!($object instanceof AbstractModel) || $object->getData($code) !== $object->getOrigData($code))
54+
) {
55+
try {
56+
$this->wysiwygValidator->validate($object->getData($code));
57+
} catch (ValidationException $exception) {
58+
$attributeException = new Exception(
59+
__(
60+
'Using restricted HTML elements for "%1". %2',
61+
$attribute->getName(),
62+
$exception->getMessage()
63+
),
64+
$exception
65+
);
66+
$attributeException->setAttributeCode($code)->setPart('backend');
67+
throw $attributeException;
68+
}
69+
}
70+
}
71+
}
72+
73+
/**
74+
* @inheritDoc
75+
*/
76+
public function beforeSave($object)
77+
{
78+
parent::beforeSave($object);
79+
$this->validateHtml($object);
80+
81+
return $this;
82+
}
83+
84+
/**
85+
* @inheritDoc
86+
*/
87+
public function validate($object)
88+
{
89+
$isValid = parent::validate($object);
90+
if ($isValid) {
91+
$this->validateHtml($object);
92+
}
93+
94+
return $isValid;
95+
}
96+
}

app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
namespace Magento\Catalog\Model\ResourceModel\Eav;
88

9+
use Magento\Catalog\Model\Attribute\Backend\DefaultBackend;
910
use Magento\Catalog\Model\Attribute\LockValidatorInterface;
11+
use Magento\Eav\Model\Entity;
1012
use Magento\Framework\Api\AttributeValueFactory;
1113
use Magento\Framework\Stdlib\DateTime\DateTimeFormatterInterface;
1214

@@ -902,4 +904,17 @@ public function setIsFilterableInGrid($isFilterableInGrid)
902904
$this->setData(self::IS_FILTERABLE_IN_GRID, $isFilterableInGrid);
903905
return $this;
904906
}
907+
908+
/**
909+
* @inheritDoc
910+
*/
911+
protected function _getDefaultBackendModel()
912+
{
913+
$backend = parent::_getDefaultBackendModel();
914+
if ($backend === Entity::DEFAULT_BACKEND_MODEL) {
915+
$backend = DefaultBackend::class;
916+
}
917+
918+
return $backend;
919+
}
905920
}
Lines changed: 23 additions & 0 deletions
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="StorefrontCheckPresentSubCategoryActionGroup">
11+
<annotations>
12+
<description>Checks for a subcategory in topmenu</description>
13+
</annotations>
14+
<arguments>
15+
<argument name="parenCategoryName" type="string"/>
16+
<argument name="childCategoryName" type="string"/>
17+
</arguments>
18+
19+
<waitForElementVisible selector="{{StorefrontHeaderSection.NavigationCategoryByName(parenCategoryName)}}" stepKey="waitForTopMenuLoaded"/>
20+
<moveMouseOver selector="{{StorefrontHeaderSection.NavigationCategoryByName(parenCategoryName)}}" stepKey="moveMouseToParentCategory"/>
21+
<seeElement selector="{{StorefrontHeaderSection.NavigationCategoryByName(childCategoryName)}}" stepKey="seeSubcategoryInTree"/>
22+
</actionGroup>
23+
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/Page/AdminCategoryEditPage.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
<section name="AdminCategoryModalSection"/>
2020
<section name="AdminCategoryMessagesSection"/>
2121
<section name="AdminCategoryContentSection"/>
22+
<section name="AdminCategoryScheduleDesignUpdateSection"/>
2223
</page>
2324
</pages>

app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryBasicFieldSection/AdminCategoryBasicFieldSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@
2222
<element name="FieldError" type="text" selector=".admin__field-error[data-bind='attr: {for: {{field}}}, text: error']" parameterized="true"/>
2323
<element name="panelFieldControl" type="input" selector="//aside//div[@data-index=&quot;{{arg1}}&quot;]/descendant::*[@name=&quot;{{arg2}}&quot;]" parameterized="true"/>
2424
<element name="productsInCategory" type="input" selector="div[data-index='assign_products']" timeout="30"/>
25+
<element name="scheduleDesignUpdateTab" type="block" selector="div[data-index='schedule_design_update']" timeout="15"/>
2526
</section>
2627
</sections>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
10+
<section name="AdminCategoryScheduleDesignUpdateSection">
11+
<element name="sectionHeader" type="button" selector="div[data-index='schedule_design_update'] .fieldset-wrapper-title" timeout="30"/>
12+
<element name="sectionBody" type="text" selector="div[data-index='schedule_design_update'] .admin__fieldset-wrapper-content"/>
13+
</section>
14+
</sections>

app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCategoryIndexerInUpdateOnScheduleModeTest.xml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,15 @@
1010
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
1111
<test name="AdminProductCategoryIndexerInUpdateOnScheduleModeTest">
1212
<annotations>
13+
<features value="Catalog"/>
1314
<stories value="Product Categories Indexer"/>
1415
<title value="Product Categories Indexer in Update on Schedule mode"/>
1516
<description value="The test verifies that in Update on Schedule mode if displaying of category products on Storefront changes due to product properties change,
1617
the changes are NOT applied immediately, but applied only after cron runs (twice)."/>
17-
<severity value="BLOCKER"/>
18-
<testCaseId value="MC-11146"/>
18+
<severity value="CRITICAL"/>
19+
<testCaseId value="MC-26119"/>
1920
<group value="catalog"/>
2021
<group value="indexer"/>
21-
<skip>
22-
<issueId value="MC-20392"/>
23-
</skip>
2422
</annotations>
2523
<before>
2624
<actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/>
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Catalog\Test\Unit\Model\Attribute\Backend;
10+
11+
use Magento\Catalog\Model\AbstractModel;
12+
use Magento\Catalog\Model\Attribute\Backend\DefaultBackend;
13+
use Magento\Framework\DataObject;
14+
use Magento\Framework\Validation\ValidationException;
15+
use Magento\Framework\Validator\HTML\WYSIWYGValidatorInterface;
16+
use PHPUnit\Framework\TestCase;
17+
use Magento\Eav\Model\Entity\Attribute as BasicAttribute;
18+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
19+
use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException;
20+
21+
class DefaultBackendTest extends TestCase
22+
{
23+
/**
24+
* Different cases for attribute validation.
25+
*
26+
* @return array
27+
*/
28+
public function getAttributeConfigurations(): array
29+
{
30+
return [
31+
'basic-attribute' => [true, false, true, 'basic', 'value', false, true, false],
32+
'non-html-attribute' => [false, false, false, 'non-html', 'value', false, false, false],
33+
'empty-html-attribute' => [false, false, true, 'html', null, false, true, false],
34+
'invalid-html-attribute' => [false, false, false, 'html', 'value', false, true, true],
35+
'valid-html-attribute' => [false, true, false, 'html', 'value', false, true, false],
36+
'changed-invalid-html-attribute' => [false, false, true, 'html', 'value', true, true, true],
37+
'changed-valid-html-attribute' => [false, true, true, 'html', 'value', true, true, false]
38+
];
39+
}
40+
41+
/**
42+
* Test attribute validation.
43+
*
44+
* @param bool $isBasic
45+
* @param bool $isValidated
46+
* @param bool $isCatalogEntity
47+
* @param string $code
48+
* @param mixed $value
49+
* @param bool $isChanged
50+
* @param bool $isHtmlAttribute
51+
* @param bool $exceptionThrown
52+
* @dataProvider getAttributeConfigurations
53+
*/
54+
public function testValidate(
55+
bool $isBasic,
56+
bool $isValidated,
57+
bool $isCatalogEntity,
58+
string $code,
59+
$value,
60+
bool $isChanged,
61+
bool $isHtmlAttribute,
62+
bool $exceptionThrown
63+
): void {
64+
if ($isBasic) {
65+
$attributeMock = $this->createMock(BasicAttribute::class);
66+
} else {
67+
$attributeMock = $this->createMock(Attribute::class);
68+
$attributeMock->expects($this->any())
69+
->method('getIsHtmlAllowedOnFront')
70+
->willReturn($isHtmlAttribute);
71+
}
72+
$attributeMock->expects($this->any())->method('getAttributeCode')->willReturn($code);
73+
74+
$validatorMock = $this->getMockForAbstractClass(WYSIWYGValidatorInterface::class);
75+
if (!$isValidated) {
76+
$validatorMock->expects($this->any())
77+
->method('validate')
78+
->willThrowException(new ValidationException(__('HTML is invalid')));
79+
} else {
80+
$validatorMock->expects($this->any())->method('validate');
81+
}
82+
83+
if ($isCatalogEntity) {
84+
$objectMock = $this->createMock(AbstractModel::class);
85+
$objectMock->expects($this->any())
86+
->method('getOrigData')
87+
->willReturn($isChanged ? $value .'-OLD' : $value);
88+
} else {
89+
$objectMock = $this->createMock(DataObject::class);
90+
}
91+
$objectMock->expects($this->any())->method('getData')->with($code)->willReturn($value);
92+
93+
$model = new DefaultBackend($validatorMock);
94+
$model->setAttribute($attributeMock);
95+
96+
$actuallyThrownForSave = false;
97+
try {
98+
$model->beforeSave($objectMock);
99+
} catch (AttributeException $exception) {
100+
$actuallyThrownForSave = true;
101+
}
102+
$actuallyThrownForValidate = false;
103+
try {
104+
$model->validate($objectMock);
105+
} catch (AttributeException $exception) {
106+
$actuallyThrownForValidate = true;
107+
}
108+
$this->assertEquals($actuallyThrownForSave, $actuallyThrownForValidate);
109+
$this->assertEquals($actuallyThrownForSave, $exceptionThrown);
110+
}
111+
}

app/code/Magento/Catalog/Test/Unit/Model/Plugin/ProductRepository/TransactionWrapperTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ protected function setUp(): void
6262
$this->closureMock = function () use ($productMock) {
6363
return $productMock;
6464
};
65-
$this->rollbackClosureMock = function () use ($productMock) {
65+
$this->rollbackClosureMock = function () {
6666
throw new \Exception(self::ERROR_MSG);
6767
};
6868

app/code/Magento/CatalogCustomerGraphQl/Model/Resolver/TierPrices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function resolve(
8787
$this->tiers->addProductFilter($productId);
8888

8989
return $this->valueFactory->create(
90-
function () use ($productId, $context) {
90+
function () use ($productId) {
9191
$tierPrices = $this->tiers->getProductTierPrices($productId);
9292

9393
return $tierPrices ?? [];

app/code/Magento/CatalogSearch/Model/Advanced.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ protected function getPreparedSearchCriteria($attribute, $value)
359359
if (is_array($value)) {
360360
if (isset($value['from']) && isset($value['to'])) {
361361
if (!empty($value['from']) || !empty($value['to'])) {
362+
$from = '';
363+
$to = '';
362364
if (isset($value['currency'])) {
363365
/** @var $currencyModel Currency */
364366
$currencyModel = $this->_currencyFactory->create()->load($value['currency']);

app/code/Magento/Checkout/Test/Mftf/ActionGroup/LoggedInUserCheckoutFillingShippingSectionActionGroup.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424
<selectOption selector="{{CheckoutShippingSection.region}}" userInput="{{customerAddressVar.state}}" stepKey="selectRegion"/>
2525
<fillField selector="{{CheckoutShippingSection.postcode}}" userInput="{{customerAddressVar.postcode}}" stepKey="enterPostcode"/>
2626
<fillField selector="{{CheckoutShippingSection.telephone}}" userInput="{{customerAddressVar.telephone}}" stepKey="enterTelephone"/>
27-
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/>
27+
<waitForPageLoad stepKey="waitForLoadingMask"/>
2828
<click selector="{{CheckoutShippingSection.firstShippingMethod}}" stepKey="selectFirstShippingMethod"/>
29-
<waitForElement selector="{{CheckoutShippingSection.next}}" time="30" stepKey="waitForNextButton"/>
29+
<waitForElementVisible selector="{{CheckoutShippingSection.next}}" time="30" stepKey="waitForNextButton"/>
30+
<waitForPageLoad stepKey="waitForShippingLoadingMask"/>
3031
<click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext"/>
31-
<waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" time="30" stepKey="waitForPaymentSectionLoaded"/>
32+
<waitForElementVisible selector="{{CheckoutPaymentSection.paymentSectionTitle}}" time="30" stepKey="waitForPaymentSectionLoaded"/>
3233
<seeInCurrentUrl url="{{CheckoutPage.url}}/#payment" stepKey="assertCheckoutPaymentUrl"/>
3334
</actionGroup>
3435
</actionGroups>

0 commit comments

Comments
 (0)