Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 8e5d2a0

Browse files
Merge branch '2.3.0-release' of github.com:magento/magento2ce into MC-4277
2 parents 3ad4214 + 32219a9 commit 8e5d2a0

File tree

53 files changed

+1835
-4261
lines changed

Some content is hidden

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

53 files changed

+1835
-4261
lines changed

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

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Catalog\Controller\Adminhtml\Product\Attribute;
1515
use Magento\Catalog\Helper\Product;
1616
use Magento\Catalog\Model\Product\Attribute\Frontend\Inputtype\Presentation;
17+
use Magento\Framework\Serialize\Serializer\FormData;
1718
use Magento\Catalog\Model\Product\AttributeSet\BuildFactory;
1819
use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory;
1920
use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator;
@@ -32,6 +33,8 @@
3233
use Magento\Framework\View\Result\PageFactory;
3334

3435
/**
36+
* Product attribute save controller.
37+
*
3538
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
3639
*/
3740
class Save extends Attribute implements HttpPostActionInterface
@@ -76,6 +79,11 @@ class Save extends Attribute implements HttpPostActionInterface
7679
*/
7780
private $presentation;
7881

82+
/**
83+
* @var FormData|null
84+
*/
85+
private $formDataSerializer;
86+
7987
/**
8088
* @param Context $context
8189
* @param FrontendInterface $attributeLabelCache
@@ -89,6 +97,7 @@ class Save extends Attribute implements HttpPostActionInterface
8997
* @param Product $productHelper
9098
* @param LayoutFactory $layoutFactory
9199
* @param Presentation|null $presentation
100+
* @param FormData|null $formDataSerializer
92101
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
93102
*/
94103
public function __construct(
@@ -103,7 +112,8 @@ public function __construct(
103112
FilterManager $filterManager,
104113
Product $productHelper,
105114
LayoutFactory $layoutFactory,
106-
Presentation $presentation = null
115+
Presentation $presentation = null,
116+
FormData $formDataSerializer = null
107117
) {
108118
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
109119
$this->buildFactory = $buildFactory;
@@ -114,19 +124,38 @@ public function __construct(
114124
$this->groupCollectionFactory = $groupCollectionFactory;
115125
$this->layoutFactory = $layoutFactory;
116126
$this->presentation = $presentation ?: ObjectManager::getInstance()->get(Presentation::class);
127+
$this->formDataSerializer = $formDataSerializer
128+
?: ObjectManager::getInstance()->get(FormData::class);
117129
}
118130

119131
/**
132+
* @inheritdoc
133+
*
120134
* @return Redirect
121135
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
122136
* @SuppressWarnings(PHPMD.NPathComplexity)
123137
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
138+
* @throws \Zend_Validate_Exception
124139
*/
125140
public function execute()
126141
{
142+
try {
143+
$optionData = $this->formDataSerializer
144+
->unserialize($this->getRequest()->getParam('serialized_options', '[]'));
145+
} catch (\InvalidArgumentException $e) {
146+
$message = __("The attribute couldn't be saved due to an error. Verify your information and try again. "
147+
. "If the error persists, please try again later.");
148+
$this->messageManager->addErrorMessage($message);
149+
return $this->returnResult('catalog/*/edit', ['_current' => true], ['error' => true]);
150+
}
151+
127152
$data = $this->getRequest()->getPostValue();
153+
$data = array_replace_recursive(
154+
$data,
155+
$optionData
156+
);
157+
128158
if ($data) {
129-
$this->preprocessOptionsData($data);
130159
$setId = $this->getRequest()->getParam('set');
131160

132161
$attributeSet = null;
@@ -135,7 +164,7 @@ public function execute()
135164
$name = trim($name);
136165

137166
try {
138-
/** @var $attributeSet Set */
167+
/** @var Set $attributeSet */
139168
$attributeSet = $this->buildFactory->create()
140169
->setEntityTypeId($this->_entityTypeId)
141170
->setSkeletonId($setId)
@@ -157,7 +186,7 @@ public function execute()
157186

158187
$attributeId = $this->getRequest()->getParam('attribute_id');
159188

160-
/** @var $model ProductAttributeInterface */
189+
/** @var ProductAttributeInterface $model */
161190
$model = $this->attributeFactory->create();
162191
if ($attributeId) {
163192
$model->load($attributeId);
@@ -189,7 +218,7 @@ public function execute()
189218

190219
//validate frontend_input
191220
if (isset($data['frontend_input'])) {
192-
/** @var $inputType Validator */
221+
/** @var Validator $inputType */
193222
$inputType = $this->validatorFactory->create();
194223
if (!$inputType->isValid($data['frontend_input'])) {
195224
foreach ($inputType->getMessages() as $message) {
@@ -317,28 +346,8 @@ public function execute()
317346
}
318347

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

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

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@
77

88
namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute;
99

10+
use Magento\Framework\Serialize\Serializer\FormData;
1011
use Magento\Framework\App\Action\HttpGetActionInterface;
1112
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
13+
use Magento\Framework\App\ObjectManager;
1214
use Magento\Framework\DataObject;
1315
use Magento\Catalog\Controller\Adminhtml\Product\Attribute as AttributeAction;
1416

17+
/**
18+
* Product attribute validate controller.
19+
*
20+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
21+
*/
1522
class Validate extends AttributeAction implements HttpGetActionInterface, HttpPostActionInterface
1623
{
1724
const DEFAULT_MESSAGE_KEY = 'message';
@@ -31,6 +38,11 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo
3138
*/
3239
private $multipleAttributeList;
3340

41+
/**
42+
* @var FormData|null
43+
*/
44+
private $formDataSerializer;
45+
3446
/**
3547
* Constructor
3648
*
@@ -41,6 +53,7 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo
4153
* @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
4254
* @param \Magento\Framework\View\LayoutFactory $layoutFactory
4355
* @param array $multipleAttributeList
56+
* @param FormData|null $formDataSerializer
4457
*/
4558
public function __construct(
4659
\Magento\Backend\App\Action\Context $context,
@@ -49,15 +62,20 @@ public function __construct(
4962
\Magento\Framework\View\Result\PageFactory $resultPageFactory,
5063
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
5164
\Magento\Framework\View\LayoutFactory $layoutFactory,
52-
array $multipleAttributeList = []
65+
array $multipleAttributeList = [],
66+
FormData $formDataSerializer = null
5367
) {
5468
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
5569
$this->resultJsonFactory = $resultJsonFactory;
5670
$this->layoutFactory = $layoutFactory;
5771
$this->multipleAttributeList = $multipleAttributeList;
72+
$this->formDataSerializer = $formDataSerializer ?: ObjectManager::getInstance()
73+
->get(FormData::class);
5874
}
5975

6076
/**
77+
* @inheritdoc
78+
*
6179
* @return \Magento\Framework\Controller\ResultInterface
6280
* @SuppressWarnings(PHPMD.NPathComplexity)
6381
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -66,6 +84,15 @@ public function execute()
6684
{
6785
$response = new DataObject();
6886
$response->setError(false);
87+
try {
88+
$optionsData = $this->formDataSerializer
89+
->unserialize($this->getRequest()->getParam('serialized_options', '[]'));
90+
} catch (\InvalidArgumentException $e) {
91+
$message = __("The attribute couldn't be validated due to an error. Verify your information and try again. "
92+
. "If the error persists, please try again later.");
93+
$this->setMessageToResponse($response, [$message]);
94+
$response->setError(true);
95+
}
6996

7097
$attributeCode = $this->getRequest()->getParam('attribute_code');
7198
$frontendLabel = $this->getRequest()->getParam('frontend_label');
@@ -105,10 +132,10 @@ public function execute()
105132
}
106133

107134
$multipleOption = $this->getRequest()->getParam("frontend_input");
108-
$multipleOption = null == $multipleOption ? 'select' : $multipleOption;
135+
$multipleOption = (null === $multipleOption) ? 'select' : $multipleOption;
109136

110-
if (isset($this->multipleAttributeList[$multipleOption]) && !(null == ($multipleOption))) {
111-
$options = $this->getRequest()->getParam($this->multipleAttributeList[$multipleOption]);
137+
if (isset($this->multipleAttributeList[$multipleOption])) {
138+
$options = $optionsData[$this->multipleAttributeList[$multipleOption]] ?? null;
112139
$this->checkUniqueOption(
113140
$response,
114141
$options
@@ -126,7 +153,8 @@ public function execute()
126153
}
127154

128155
/**
129-
* Throws Exception if not unique values into options
156+
* Throws Exception if not unique values into options.
157+
*
130158
* @param array $optionsValues
131159
* @param array $deletedOptions
132160
* @return bool
@@ -160,6 +188,8 @@ private function setMessageToResponse($response, $messages)
160188
}
161189

162190
/**
191+
* Performs checking the uniqueness of the attribute options.
192+
*
163193
* @param DataObject $response
164194
* @param array|null $options
165195
* @return $this

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
</arguments>
1515
<amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/>
1616
<waitForPageLoad stepKey="waitForPageLoad1"/>
17-
<click selector="{{AdminProductAttributeGridSection.AttributeCode(ProductAttribute.attribute_code)}}" stepKey="navigateToAttributeEditPage1" />
17+
<fillField selector="{{AdminProductAttributeGridSection.FilterByAttributeCode}}"
18+
userInput="{{ProductAttribute.attribute_code}}" stepKey="setAttributeCode"/>
19+
<click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeFromTheGrid"/>
20+
<click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/>
1821
<waitForPageLoad stepKey="waitForPageLoad2" />
1922
</actionGroup>
2023
</actionGroups>

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
<element name="DefaultValue" type="input" selector="#default_value_text"/>
1818
<element name="Scope" type="select" selector="#is_global"/>
1919
<element name="Save" type="button" selector="#save" timeout="30"/>
20+
<element name="DeleteAttribute" type="button" selector="#delete" timeout="30"/>
2021
<element name="SaveAndEdit" type="button" selector="#save_and_edit_button" timeout="30"/>
2122
<element name="TinyMCE4" type="button" selector="//span[text()='Default Value']/parent::label/following-sibling::div//div[@class='mce-branding-powered-by']"/>
2223
<element name="checkIfTabOpen" selector="//div[@id='advanced_fieldset-wrapper' and not(contains(@class,'opened'))]" type="button"/>
2324
<element name="useInLayeredNavigation" type="select" selector="#is_filterable"/>
2425
</section>
2526
<section name="StorefrontPropertiesSection">
27+
<element name="PageTitle" type="text" selector="//span[text()='Storefront Properties']" />
2628
<element name="StoreFrontPropertiesTab" selector="#product_attribute_tabs_front" type="button"/>
2729
<element name="EnableWYSIWYG" type="select" selector="#enabled"/>
2830
<element name="useForPromoRuleConditions" type="select" selector="#is_used_for_promo_rules"/>
@@ -63,4 +65,12 @@
6365
<element name="SpecialCharacter" type="button" selector=".mce-i-charmap" />
6466
<element name="TextArea" type="input" selector="#default_value_textarea" />
6567
</section>
68+
<section name="AdvancedAttributePropertiesSection">
69+
<element name="AdvancedAttributePropertiesSectionToggle"
70+
type="button" selector="#advanced_fieldset-wrapper"/>
71+
<element name="AttributeCode" type="text" selector="#attribute_code"/>
72+
<element name="Scope" type="select" selector="#is_global"/>
73+
<element name="AddToColumnOptions" type="select" selector="#is_used_in_grid"/>
74+
<element name="UseInFilterOptions" type="select" selector="#is_filterable_in_grid"/>
75+
</section>
6676
</sections>

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@
2626
<requiredEntity createDataKey="myProductAttributeCreation"/>
2727
</createData>
2828
</before>
29-
<amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid1"/>
30-
<waitForPageLoad stepKey="waitForPageLoad1"/>
31-
<click selector="{{AdminProductAttributeGridSection.AttributeCode($$myProductAttributeCreation.attribute_code$$)}}" stepKey="navigateToAttributeEditPage1" />
32-
<waitForPageLoad stepKey="waitForPageLoad2" />
29+
<actionGroup ref="navigateToCreatedProductAttribute" stepKey="navigateToAttribute">
30+
<argument name="ProductAttribute" value="productAttributeWysiwyg"/>
31+
</actionGroup>
3332
<seeOptionIsSelected selector="{{AttributePropertiesSection.InputType}}" userInput="Text Editor" stepKey="seeTextEditorSelected" />
3433
<see selector="{{AttributePropertiesSection.InputType}}" userInput="Text Area" stepKey="seeTextArea1" />
3534
<selectOption selector="{{AttributePropertiesSection.InputType}}" userInput="Text Area" stepKey="selectTextArea" />

0 commit comments

Comments
 (0)