Skip to content

Commit db6b440

Browse files
author
Sergey Shvets
committed
Merge remote-tracking branch 'origin/MAGETWO-54780' into MAGETWO-55814
2 parents 2db9e0f + 8241423 commit db6b440

File tree

11 files changed

+532
-12
lines changed

11 files changed

+532
-12
lines changed

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public function __construct(
3939
\Magento\Framework\View\Result\PageFactory $resultPageFactory,
4040
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
4141
\Magento\Framework\View\LayoutFactory $layoutFactory
42-
) {
42+
)
43+
{
4344
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
4445
$this->resultJsonFactory = $resultJsonFactory;
4546
$this->layoutFactory = $layoutFactory;
@@ -89,9 +90,35 @@ public function execute()
8990
$response->setHtmlMessage($layout->getMessagesBlock()->getGroupedHtml());
9091
}
9192
}
93+
94+
$options = $this->getRequest()->getParam("option");
95+
if (is_array($options)) {
96+
if (!$this->isUniqueAdminValues($options['value'], $options['delete'])) {
97+
$this->setMessageToResponse($response, [__("The value of Admin must be unique.")]);
98+
$response->setError(true);
99+
};
100+
}
92101
return $this->resultJsonFactory->create()->setJsonData($response->toJson());
93102
}
94103

104+
/**
105+
* Throws Exception if not unique values into options
106+
* @param array $optionsValues
107+
* @param array $deletedOptions
108+
* @return bool
109+
*/
110+
private function isUniqueAdminValues(array $optionsValues, array $deletedOptions)
111+
{
112+
$adminValues = array();
113+
foreach ($optionsValues as $optionKey => $values) {
114+
if (!(isset($deletedOptions[$optionKey]) and $deletedOptions[$optionKey] === '1')) {
115+
$adminValues[] = reset($values);
116+
}
117+
}
118+
$uniqueValues = array_unique($adminValues);
119+
return ($uniqueValues === $adminValues);
120+
}
121+
95122
/**
96123
* Set message to response object
97124
*

app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute;
77

88
use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate;
9-
use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest;
10-
use Magento\Framework\Controller\Result\JsonFactory as ResultJsonFactory;
11-
use Magento\Framework\Controller\Result\Json as ResultJson;
12-
use Magento\Framework\View\LayoutFactory;
13-
use Magento\Framework\ObjectManagerInterface;
149
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
10+
use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest;
1511
use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
12+
use Magento\Framework\Controller\Result\Json as ResultJson;
13+
use Magento\Framework\Controller\Result\JsonFactory as ResultJsonFactory;
1614
use Magento\Framework\Escaper;
15+
use Magento\Framework\ObjectManagerInterface;
16+
use Magento\Framework\View\LayoutFactory;
1717
use Magento\Framework\View\LayoutInterface;
1818

1919
/**
@@ -147,4 +147,97 @@ public function testExecute()
147147

148148
$this->assertInstanceOf(ResultJson::class, $this->getModel()->execute());
149149
}
150+
151+
/**
152+
* @dataProvider provideUniqueData
153+
* @param array $options
154+
* @param boolean $isError
155+
*/
156+
public function testUniqueValidation(array $options, $isError)
157+
{
158+
$countFunctionCalls = ($isError) ? 5 : 4;
159+
$this->requestMock->expects($this->exactly($countFunctionCalls))
160+
->method('getParam')
161+
->willReturnMap([
162+
['frontend_label', null, 'test_frontend_label'],
163+
['attribute_code', null, "test_attribute_code"],
164+
['new_attribute_set_name', null, 'test_attribute_set_name'],
165+
['option', null, $options],
166+
['message_key', null, Validate::DEFAULT_MESSAGE_KEY]
167+
]);
168+
169+
$this->objectManagerMock->expects($this->once())
170+
->method('create')
171+
->willReturn($this->attributeMock);
172+
173+
$this->attributeMock->expects($this->once())
174+
->method('loadByCode')
175+
->willReturnSelf();
176+
177+
$this->requestMock->expects($this->once())
178+
->method('has')
179+
->with('new_attribute_set_name')
180+
->willReturn(false);
181+
182+
$this->resultJsonFactoryMock->expects($this->once())
183+
->method('create')
184+
->willReturn($this->resultJson);
185+
186+
$this->resultJson->expects($this->once())
187+
->method('setJsonData')
188+
->willReturnSelf();
189+
190+
$this->assertInstanceOf(ResultJson::class, $this->getModel()->execute());
191+
}
192+
193+
public function provideUniqueData()
194+
{
195+
return [
196+
// valid options
197+
[
198+
[
199+
'value' => [
200+
"option_0" => [1, 0],
201+
"option_1" => [2, 0],
202+
"option_2" => [3, 0],
203+
],
204+
'delete' => [
205+
"option_0" => "",
206+
"option_1" => "",
207+
"option_2" => "",
208+
]
209+
], false
210+
],
211+
//with duplicate
212+
[
213+
[
214+
'value' => [
215+
"option_0" => [1, 0],
216+
"option_1" => [1, 0],
217+
"option_2" => [3, 0],
218+
],
219+
'delete' => [
220+
"option_0" => "",
221+
"option_1" => "",
222+
"option_2" => "",
223+
]
224+
], true
225+
],
226+
//with duplicate but deleted
227+
[
228+
[
229+
'value' => [
230+
"option_0" => [1, 0],
231+
"option_1" => [1, 0],
232+
"option_2" => [3, 0],
233+
],
234+
'delete' => [
235+
"option_0" => "",
236+
"option_1" => "1",
237+
"option_2" => "",
238+
]
239+
], false
240+
],
241+
];
242+
}
150243
}

app/code/Magento/Catalog/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,3 +715,4 @@ Disable,Disable
715715
none,none
716716
Overview,Overview
717717
Details,Details
718+
"The value of Admin must be unique.", "The value of Admin must be unique."

app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/options.phtml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ $stores = $block->getStoresSortedBySortOrder();
3434
<tr>
3535
<th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="validation">
3636
<input type="hidden" class="required-dropdown-attribute-entry" name="dropdown_attribute_validation"/>
37+
<input type="hidden" class="required-dropdown-attribute-unique" name="dropdown_attribute_validation_unique"/>
3738
</th>
3839
</tr>
3940
<tr>
@@ -62,7 +63,7 @@ $stores = $block->getStoresSortedBySortOrder();
6263
<input class="input-radio" type="<%- data.intype %>" name="default[]" value="<%- data.id %>" <%- data.checked %><?php if ($block->getReadOnly()):?>disabled="disabled"<?php endif;?>/>
6364
</td>
6465
<?php foreach ($stores as $_store): ?>
65-
<td class="col-<%- data.id %>"><input name="option[value][<%- data.id %>][<?php /* @escapeNotVerified */ echo $_store->getId() ?>]" value="<%- data.store<?php /* @escapeNotVerified */ echo $_store->getId() ?> %>" class="input-text<?php if ($_store->getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> required-option<?php endif; ?>" type="text" <?php if ($block->getReadOnly() || $block->canManageOptionDefaultOnly()):?> disabled="disabled"<?php endif;?>/></td>
66+
<td class="col-<%- data.id %>"><input name="option[value][<%- data.id %>][<?php /* @escapeNotVerified */ echo $_store->getId() ?>]" value="<%- data.store<?php /* @escapeNotVerified */ echo $_store->getId() ?> %>" class="input-text<?php if ($_store->getId() == \Magento\Store\Model\Store::DEFAULT_STORE_ID): ?> required-option required-unique<?php endif; ?>" type="text" <?php if ($block->getReadOnly() || $block->canManageOptionDefaultOnly()):?> disabled="disabled"<?php endif;?>/></td>
6667
<?php endforeach; ?>
6768
<td id="delete_button_container_<%- data.id %>" class="col-delete">
6869
<input type="hidden" class="delete-flag" name="option[delete][<%- data.id %>]" value="" />
@@ -90,6 +91,10 @@ $stores = $block->getStoresSortedBySortOrder();
9091
"attributesData": <?php /* @noEscape */ echo json_encode($values, JSON_HEX_QUOT); ?>,
9192
"isSortable": <?php echo (int)(!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()) ?>,
9293
"isReadOnly": <?php echo (int)$block->getReadOnly(); ?>
94+
},
95+
"Magento_Catalog/catalog/product/attribute/unique-validate": {
96+
"element": "required-dropdown-attribute-unique",
97+
"message": "<?php echo __("The value of Admin must be unique.") ?>"
9398
}
9499
}
95100
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Copyright © 2016 Magento. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
/* global $break $ $$ */
7+
8+
define([
9+
'jquery',
10+
'mage/backend/validation'
11+
], function (jQuery) {
12+
'use strict';
13+
14+
return function (config) {
15+
var _config = jQuery.extend({
16+
element: null,
17+
message: "",
18+
uniqueClass: 'required-unique'
19+
}, config);
20+
21+
if (typeof _config.element === "string") {
22+
jQuery.validator.addMethod(
23+
_config.element,
24+
25+
function (value, element) {
26+
var inputs = jQuery(element)
27+
.closest("table")
28+
.find('.' + _config.uniqueClass + ":visible"),
29+
valuesHash = {},
30+
isValid = true;
31+
32+
inputs.each(function (el) {
33+
var inputValue = inputs[el].value;
34+
if (typeof valuesHash[inputValue] !== "undefined") {
35+
isValid = false;
36+
}
37+
valuesHash[inputValue] = el;
38+
});
39+
return isValid;
40+
},
41+
42+
_config.message
43+
);
44+
}
45+
};
46+
});
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Plugin;
8+
9+
use Magento\Catalog\Controller\Adminhtml\Product\Attribute;
10+
use Magento\Framework\Controller\Result\Json;
11+
use Magento\Framework\DataObject;
12+
13+
/**
14+
* Class Save
15+
* @package Magento\Swatches\Controller\Adminhtml\Product\Attribute\Plugin
16+
*/
17+
class Validate
18+
{
19+
/**
20+
* @param Attribute\Validate $subject
21+
* @param Json $response
22+
* @return array
23+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
24+
*/
25+
public function afterExecute(Attribute\Validate $subject, Json $response)
26+
{
27+
$data = $subject->getRequest()->getPostValue();
28+
if (isset($data['frontend_input'])) {
29+
$dataIndex = false;
30+
switch ($data['frontend_input']) {
31+
case "select":
32+
$dataIndex = "option";
33+
break;
34+
case "swatch_text":
35+
$dataIndex = "optiontext";
36+
break;
37+
case "swatch_visual":
38+
$dataIndex = "optionvisual";
39+
break;
40+
}
41+
42+
if ($dataIndex !== false) {
43+
if (!$this->isUniqueAdminValues($data[$dataIndex]['value'], $data[$dataIndex]['delete'])) {
44+
$response->setJsonData($this->createErrorResponse("The value of Admin must be unique.")->toJson());
45+
};
46+
}
47+
}
48+
49+
return $response;
50+
}
51+
52+
/**
53+
* Throws Exception if not unique values into options
54+
* @param array $optionsValues
55+
* @param array $deletedOptions
56+
* @return bool
57+
*/
58+
private function isUniqueAdminValues(array $optionsValues, array $deletedOptions)
59+
{
60+
$adminValues = array();
61+
foreach ($optionsValues as $optionKey => $values) {
62+
if (!(isset($deletedOptions[$optionKey]) and $deletedOptions[$optionKey] === '1')) {
63+
$adminValues[] = reset($values);
64+
}
65+
}
66+
$uniqueValues = array_unique($adminValues);
67+
return ($uniqueValues === $adminValues);
68+
}
69+
70+
/**
71+
* @param string $message
72+
* @return DataObject
73+
*/
74+
private function createErrorResponse($message)
75+
{
76+
$error = new DataObject();
77+
$error->setError(true);
78+
$error->setData(Attribute\Validate ::DEFAULT_MESSAGE_KEY, __($message));
79+
return $error;
80+
}
81+
}

0 commit comments

Comments
 (0)