Skip to content

Commit b060898

Browse files
author
Magento CICD
authored
merge magento/2.2.7-develop into magento-pangolin/2.2.7-dev-pan-2.3.8
2 parents 07e2075 + 46b8319 commit b060898

File tree

29 files changed

+921
-171
lines changed

29 files changed

+921
-171
lines changed

app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
<element name="test" type="input" selector=".test"/>
1212
<element name="success" type="text" selector="#messages div.message-success"/>
1313
<element name="successMessageByIndex" type="text" selector=".message.message-success.success:nth-of-type({{n}})>div" parameterized="true"/>
14+
<element name="error" type="text" selector="#messages div.message-error"/>
1415
</section>
1516
</sections>

app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator;
1919
use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory;
2020
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory;
21+
use Magento\Framework\App\ObjectManager;
22+
use Magento\Framework\Serialize\Serializer\FormData;
2123
use Magento\Framework\Cache\FrontendInterface;
2224
use Magento\Framework\Controller\ResultFactory;
2325
use Magento\Framework\Controller\Result\Json;
@@ -68,6 +70,11 @@ class Save extends Attribute
6870
*/
6971
private $layoutFactory;
7072

73+
/**
74+
* @var FormData
75+
*/
76+
private $formDataSerializer;
77+
7178
/**
7279
* @param Context $context
7380
* @param FrontendInterface $attributeLabelCache
@@ -80,6 +87,7 @@ class Save extends Attribute
8087
* @param FilterManager $filterManager
8188
* @param Product $productHelper
8289
* @param LayoutFactory $layoutFactory
90+
* @param FormData|null $formDataSerializer
8391
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
8492
*/
8593
public function __construct(
@@ -93,7 +101,8 @@ public function __construct(
93101
CollectionFactory $groupCollectionFactory,
94102
FilterManager $filterManager,
95103
Product $productHelper,
96-
LayoutFactory $layoutFactory
104+
LayoutFactory $layoutFactory,
105+
FormData $formDataSerializer = null
97106
) {
98107
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
99108
$this->buildFactory = $buildFactory;
@@ -103,19 +112,37 @@ public function __construct(
103112
$this->validatorFactory = $validatorFactory;
104113
$this->groupCollectionFactory = $groupCollectionFactory;
105114
$this->layoutFactory = $layoutFactory;
115+
$this->formDataSerializer = $formDataSerializer ?? ObjectManager::getInstance()->get(FormData::class);
106116
}
107117

108118
/**
109-
* @return Redirect
119+
* @inheritdoc
120+
*
110121
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
111122
* @SuppressWarnings(PHPMD.NPathComplexity)
112123
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
113124
*/
114125
public function execute()
115126
{
127+
try {
128+
$optionData = $this->formDataSerializer->unserialize(
129+
$this->getRequest()->getParam('serialized_options', '[]')
130+
);
131+
} catch (\InvalidArgumentException $e) {
132+
$message = __("The attribute couldn't be saved due to an error. Verify your information and try again. "
133+
. "If the error persists, please try again later.");
134+
$this->messageManager->addErrorMessage($message);
135+
136+
return $this->returnResult('catalog/*/edit', ['_current' => true], ['error' => true]);
137+
}
138+
116139
$data = $this->getRequest()->getPostValue();
140+
$data = array_replace_recursive(
141+
$data,
142+
$optionData
143+
);
144+
117145
if ($data) {
118-
$this->preprocessOptionsData($data);
119146
$setId = $this->getRequest()->getParam('set');
120147

121148
$attributeSet = null;
@@ -124,7 +151,7 @@ public function execute()
124151
$name = trim($name);
125152

126153
try {
127-
/** @var $attributeSet Set */
154+
/** @var Set $attributeSet */
128155
$attributeSet = $this->buildFactory->create()
129156
->setEntityTypeId($this->_entityTypeId)
130157
->setSkeletonId($setId)
@@ -147,7 +174,7 @@ public function execute()
147174

148175
$attributeId = $this->getRequest()->getParam('attribute_id');
149176

150-
/** @var $model ProductAttributeInterface */
177+
/** @var ProductAttributeInterface $model */
151178
$model = $this->attributeFactory->create();
152179
if ($attributeId) {
153180
$model->load($attributeId);
@@ -180,7 +207,7 @@ public function execute()
180207

181208
//validate frontend_input
182209
if (isset($data['frontend_input'])) {
183-
/** @var $inputType Validator */
210+
/** @var Validator $inputType */
184211
$inputType = $this->validatorFactory->create();
185212
if (!$inputType->isValid($data['frontend_input'])) {
186213
foreach ($inputType->getMessages() as $message) {
@@ -313,28 +340,8 @@ public function execute()
313340
}
314341

315342
/**
316-
* Extract options data from serialized options field and append to data array.
317-
*
318-
* This logic is required to overcome max_input_vars php limit
319-
* that may vary and/or be inaccessible to change on different instances.
343+
* Provides an initialized Result object.
320344
*
321-
* @param array $data
322-
* @return void
323-
*/
324-
private function preprocessOptionsData(&$data)
325-
{
326-
if (isset($data['serialized_options'])) {
327-
$serializedOptions = json_decode($data['serialized_options'], JSON_OBJECT_AS_ARRAY);
328-
foreach ($serializedOptions as $serializedOption) {
329-
$option = [];
330-
parse_str($serializedOption, $option);
331-
$data = array_replace_recursive($data, $option);
332-
}
333-
}
334-
unset($data['serialized_options']);
335-
}
336-
337-
/**
338345
* @param string $path
339346
* @param array $params
340347
* @param array $response

app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
66
*/
77
namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute;
88

9+
use Magento\Framework\Serialize\Serializer\FormData;
10+
use Magento\Framework\App\ObjectManager;
911
use Magento\Framework\DataObject;
1012

13+
/**
14+
* Product attribute validate controller.
15+
*
16+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
17+
*/
1118
class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute
1219
{
1320
const DEFAULT_MESSAGE_KEY = 'message';
@@ -27,6 +34,11 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute
2734
*/
2835
private $multipleAttributeList;
2936

37+
/**
38+
* @var FormData
39+
*/
40+
private $formDataSerializer;
41+
3042
/**
3143
* Constructor
3244
*
@@ -37,6 +49,7 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute
3749
* @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
3850
* @param \Magento\Framework\View\LayoutFactory $layoutFactory
3951
* @param array $multipleAttributeList
52+
* @param FormData|null $formDataSerializer
4053
*/
4154
public function __construct(
4255
\Magento\Backend\App\Action\Context $context,
@@ -45,23 +58,36 @@ public function __construct(
4558
\Magento\Framework\View\Result\PageFactory $resultPageFactory,
4659
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
4760
\Magento\Framework\View\LayoutFactory $layoutFactory,
48-
array $multipleAttributeList = []
61+
array $multipleAttributeList = [],
62+
FormData $formDataSerializer = null
4963
) {
5064
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
5165
$this->resultJsonFactory = $resultJsonFactory;
5266
$this->layoutFactory = $layoutFactory;
5367
$this->multipleAttributeList = $multipleAttributeList;
68+
$this->formDataSerializer = $formDataSerializer ?? ObjectManager::getInstance()->get(FormData::class);
5469
}
5570

5671
/**
57-
* @return \Magento\Framework\Controller\ResultInterface
72+
* @inheritdoc
73+
*
5874
* @SuppressWarnings(PHPMD.NPathComplexity)
5975
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
6076
*/
6177
public function execute()
6278
{
6379
$response = new DataObject();
6480
$response->setError(false);
81+
try {
82+
$optionsData = $this->formDataSerializer->unserialize(
83+
$this->getRequest()->getParam('serialized_options', '[]')
84+
);
85+
} catch (\InvalidArgumentException $e) {
86+
$message = __("The attribute couldn't be validated due to an error. Verify your information and try again. "
87+
. "If the error persists, please try again later.");
88+
$this->setMessageToResponse($response, [$message]);
89+
$response->setError(true);
90+
}
6591

6692
$attributeCode = $this->getRequest()->getParam('attribute_code');
6793
$frontendLabel = $this->getRequest()->getParam('frontend_label');
@@ -101,10 +127,10 @@ public function execute()
101127
}
102128

103129
$multipleOption = $this->getRequest()->getParam("frontend_input");
104-
$multipleOption = null == $multipleOption ? 'select' : $multipleOption;
130+
$multipleOption = (null === $multipleOption) ? 'select' : $multipleOption;
105131

106132
if (isset($this->multipleAttributeList[$multipleOption]) && !(null == ($multipleOption))) {
107-
$options = $this->getRequest()->getParam($this->multipleAttributeList[$multipleOption]);
133+
$options = $optionsData[$this->multipleAttributeList[$multipleOption]] ?? null;
108134
$this->checkUniqueOption(
109135
$response,
110136
$options
@@ -122,7 +148,8 @@ public function execute()
122148
}
123149

124150
/**
125-
* Throws Exception if not unique values into options
151+
* Throws Exception if not unique values into options.
152+
*
126153
* @param array $optionsValues
127154
* @param array $deletedOptions
128155
* @return bool
@@ -156,6 +183,8 @@ private function setMessageToResponse($response, $messages)
156183
}
157184

158185
/**
186+
* Performs checking the uniqueness of the attribute options.
187+
*
159188
* @param DataObject $response
160189
* @param array|null $options
161190
* @return $this
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="deleteProductAttribute">
12+
<arguments>
13+
<argument name="ProductAttribute"/>
14+
</arguments>
15+
<amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/>
16+
<waitForPageLoad stepKey="waitForAttributeGridPageLoad"/>
17+
<fillField selector="{{AdminProductAttributeGridSection.gridFilterAttributeCode}}"
18+
userInput="{{ProductAttribute.attribute_code}}" stepKey="setAttributeCode"/>
19+
<click selector="{{AdminProductAttributeGridSection.search}}" stepKey="searchForAttributeFromTheGrid"/>
20+
<click selector="{{AdminProductAttributeGridSection.firstRow}}" stepKey="clickOnAttributeRow"/>
21+
<waitForPageLoad stepKey="waitForAttributeEditPageLoad" />
22+
<click selector="{{AttributePropertiesSection.deleteAttribute}}" stepKey="deleteAttribute"/>
23+
<waitForElement selector="{{AdminConfirmationModalSection.message}}" stepKey="waitForDeleteConfirmation"/>
24+
<see selector="{{AdminConfirmationModalSection.message}}" userInput="Are you sure you want to do this?" stepKey="seeConfirmationMessage"/>
25+
<click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmDeleteAttribute"/>
26+
<waitForPageLoad stepKey="waitForPageLoadAfterDeleteAttribute"/>
27+
<see selector="{{AdminMessagesSection.success}}" userInput="You deleted the product attribute." stepKey="seeDeleteSuccessMessage"/>
28+
</actionGroup>
29+
</actionGroups>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
<page name="ProductAttributePage" url="catalog/product_attribute/new/" area="admin" module="Magento_Catalog">
1111
<section name="AttributePropertiesSection"/>
1212
<section name="StorefrontPropertiesSection"/>
13+
<section name="AdvancedAttributePropertiesSection"/>
1314
</page>
1415
</pages>

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,22 @@
1111
<section name="AttributePropertiesSection">
1212
<element name="AdvancedProperties" type="button" selector="#advanced_fieldset-wrapper"/>
1313
<element name="Save" type="button" selector="#save"/>
14+
<element name="defaultLabel" type="input" selector="#attribute_label"/>
15+
<element name="inputType" type="select" selector="#frontend_input"/>
16+
<element name="deleteAttribute" type="button" selector="#delete" timeout="30"/>
17+
</section>
18+
<section name="StorefrontPropertiesSection">
19+
<element name="pageTitle" type="text" selector="//span[text()='Storefront Properties']" />
20+
<element name="storeFrontPropertiesTab" selector="#product_attribute_tabs_front" type="button"/>
21+
<element name="enableWYSIWYG" type="select" selector="#enabled"/>
22+
<element name="useForPromoRuleConditions" type="select" selector="#is_used_for_promo_rules"/>
23+
</section>
24+
<section name="AdvancedAttributePropertiesSection">
25+
<element name="advancedAttributePropertiesSectionToggle"
26+
type="button" selector="#advanced_fieldset-wrapper"/>
27+
<element name="attributeCode" type="text" selector="#attribute_code"/>
28+
<element name="scope" type="select" selector="#is_global"/>
29+
<element name="addToColumnOptions" type="select" selector="#is_used_in_grid"/>
30+
<element name="useInFilterOptions" type="select" selector="#is_filterable_in_grid"/>
1431
</section>
1532
</sections>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<element name="attributeCode" type="text" selector="//td[contains(text(),'{{var1}}')]" parameterized="true"/>
1313
<element name="createNewAttributeBtn" type="button" selector="#add"/>
1414
<element name="gridFilterFrontEndLabel" type="input" selector="#attributeGrid_filter_frontend_label"/>
15+
<element name="gridFilterAttributeCode" type="input" selector="#attributeGrid_filter_attribute_code"/>
1516
<element name="search" type="button" selector="button[data-action=grid-filter-apply]" timeout="30"/>
1617
<element name="resetFilter" type="button" selector="button[data-action='grid-filter-reset']" timeout="30"/>
1718
<element name="firstRow" type="button" selector="//*[@id='attributeGrid_table']/tbody/tr[1]"/>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<click selector="{{AdminProductAttributeGridSection.firstRow}}" stepKey="clickOnAttributeRow1"/>
2929
<waitForPageLoad stepKey="wait2"/>
3030
<click selector="{{AdminNewAttributePanelSection.isDefault('1')}}" stepKey="resetOptionForStatusAttribute"/>
31-
<click selector="{{AttributePropertiesSection.save}}" stepKey="saveAttribute1"/>
31+
<click selector="{{AttributePropertiesSection.Save}}" stepKey="saveAttribute1"/>
3232
<waitForPageLoad stepKey="waitForSaveAttribute1"/>
3333
<actionGroup ref="ClearCacheActionGroup" stepKey="clearCache1"/>
3434
<actionGroup ref="logout" stepKey="logoutOfAdmin"/>
@@ -42,7 +42,7 @@
4242
<click selector="{{AdminProductAttributeGridSection.firstRow}}" stepKey="clickOnAttributeRow"/>
4343
<waitForPageLoad stepKey="wait2"/>
4444
<click selector="{{AdminNewAttributePanelSection.isDefault('2')}}" stepKey="chooseDisabledOptionForStatus"/>
45-
<click selector="{{AttributePropertiesSection.save}}" stepKey="saveAttribute"/>
45+
<click selector="{{AttributePropertiesSection.Save}}" stepKey="saveAttribute"/>
4646
<waitForPageLoad stepKey="waitForAttributeToSave"/>
4747
<actionGroup ref="ClearCacheActionGroup" stepKey="clearCache"/>
4848
<amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/>

0 commit comments

Comments
 (0)