Skip to content

Commit

Permalink
MAGETWO-54780: [GitHub] Validate attribute values #4881
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Shvets committed Jul 15, 2016
1 parent 4d8ec01 commit 8241423
Show file tree
Hide file tree
Showing 11 changed files with 532 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public function __construct(
\Magento\Framework\View\Result\PageFactory $resultPageFactory,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Magento\Framework\View\LayoutFactory $layoutFactory
) {
)
{
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
$this->resultJsonFactory = $resultJsonFactory;
$this->layoutFactory = $layoutFactory;
Expand Down Expand Up @@ -89,9 +90,35 @@ public function execute()
$response->setHtmlMessage($layout->getMessagesBlock()->getGroupedHtml());
}
}

$options = $this->getRequest()->getParam("option");
if (is_array($options)) {
if (!$this->isUniqueAdminValues($options['value'], $options['delete'])) {
$this->setMessageToResponse($response, [__("The value of Admin must be unique.")]);
$response->setError(true);
};
}
return $this->resultJsonFactory->create()->setJsonData($response->toJson());
}

/**
* Throws Exception if not unique values into options
* @param array $optionsValues
* @param array $deletedOptions
* @return bool
*/
private function isUniqueAdminValues(array $optionsValues, array $deletedOptions)
{
$adminValues = array();
foreach ($optionsValues as $optionKey => $values) {
if (!(isset($deletedOptions[$optionKey]) and $deletedOptions[$optionKey] === '1')) {
$adminValues[] = reset($values);
}
}
$uniqueValues = array_unique($adminValues);
return ($uniqueValues === $adminValues);
}

/**
* Set message to response object
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute;

use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate;
use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest;
use Magento\Framework\Controller\Result\JsonFactory as ResultJsonFactory;
use Magento\Framework\Controller\Result\Json as ResultJson;
use Magento\Framework\View\LayoutFactory;
use Magento\Framework\ObjectManagerInterface;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest;
use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
use Magento\Framework\Controller\Result\Json as ResultJson;
use Magento\Framework\Controller\Result\JsonFactory as ResultJsonFactory;
use Magento\Framework\Escaper;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\View\LayoutFactory;
use Magento\Framework\View\LayoutInterface;

/**
Expand Down Expand Up @@ -147,4 +147,97 @@ public function testExecute()

$this->assertInstanceOf(ResultJson::class, $this->getModel()->execute());
}

/**
* @dataProvider provideUniqueData
* @param array $options
* @param boolean $isError
*/
public function testUniqueValidation(array $options, $isError)
{
$countFunctionCalls = ($isError) ? 5 : 4;
$this->requestMock->expects($this->exactly($countFunctionCalls))
->method('getParam')
->willReturnMap([
['frontend_label', null, 'test_frontend_label'],
['attribute_code', null, "test_attribute_code"],
['new_attribute_set_name', null, 'test_attribute_set_name'],
['option', null, $options],
['message_key', null, Validate::DEFAULT_MESSAGE_KEY]
]);

$this->objectManagerMock->expects($this->once())
->method('create')
->willReturn($this->attributeMock);

$this->attributeMock->expects($this->once())
->method('loadByCode')
->willReturnSelf();

$this->requestMock->expects($this->once())
->method('has')
->with('new_attribute_set_name')
->willReturn(false);

$this->resultJsonFactoryMock->expects($this->once())
->method('create')
->willReturn($this->resultJson);

$this->resultJson->expects($this->once())
->method('setJsonData')
->willReturnSelf();

$this->assertInstanceOf(ResultJson::class, $this->getModel()->execute());
}

public function provideUniqueData()
{
return [
// valid options
[
[
'value' => [
"option_0" => [1, 0],
"option_1" => [2, 0],
"option_2" => [3, 0],
],
'delete' => [
"option_0" => "",
"option_1" => "",
"option_2" => "",
]
], false
],
//with duplicate
[
[
'value' => [
"option_0" => [1, 0],
"option_1" => [1, 0],
"option_2" => [3, 0],
],
'delete' => [
"option_0" => "",
"option_1" => "",
"option_2" => "",
]
], true
],
//with duplicate but deleted
[
[
'value' => [
"option_0" => [1, 0],
"option_1" => [1, 0],
"option_2" => [3, 0],
],
'delete' => [
"option_0" => "",
"option_1" => "1",
"option_2" => "",
]
], false
],
];
}
}
1 change: 1 addition & 0 deletions app/code/Magento/Catalog/i18n/en_US.csv
Original file line number Diff line number Diff line change
Expand Up @@ -714,3 +714,4 @@ Disable,Disable
none,none
Overview,Overview
Details,Details
"The value of Admin must be unique.", "The value of Admin must be unique."
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ $stores = $block->getStoresSortedBySortOrder();
<tr>
<th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="validation">
<input type="hidden" class="required-dropdown-attribute-entry" name="dropdown_attribute_validation"/>
<input type="hidden" class="required-dropdown-attribute-unique" name="dropdown_attribute_validation_unique"/>
</th>
</tr>
<tr>
Expand Down Expand Up @@ -62,7 +63,7 @@ $stores = $block->getStoresSortedBySortOrder();
<input class="input-radio" type="<%- data.intype %>" name="default[]" value="<%- data.id %>" <%- data.checked %><?php if ($block->getReadOnly()):?>disabled="disabled"<?php endif;?>/>
</td>
<?php foreach ($stores as $_store): ?>
<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>
<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>
<?php endforeach; ?>
<td id="delete_button_container_<%- data.id %>" class="col-delete">
<input type="hidden" class="delete-flag" name="option[delete][<%- data.id %>]" value="" />
Expand Down Expand Up @@ -90,6 +91,10 @@ $stores = $block->getStoresSortedBySortOrder();
"attributesData": <?php /* @noEscape */ echo json_encode($values, JSON_HEX_QUOT); ?>,
"isSortable": <?php echo (int)(!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()) ?>,
"isReadOnly": <?php echo (int)$block->getReadOnly(); ?>
},
"Magento_Catalog/catalog/product/attribute/unique-validate": {
"element": "required-dropdown-attribute-unique",
"message": "<?php echo __("The value of Admin must be unique.") ?>"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

/* global $break $ $$ */

define([
'jquery',
'mage/backend/validation'
], function (jQuery) {
'use strict';

return function (config) {
var _config = jQuery.extend({
element: null,
message: "",
uniqueClass: 'required-unique'
}, config);

if (typeof _config.element === "string") {
jQuery.validator.addMethod(
_config.element,

function (value, element) {
var inputs = jQuery(element)
.closest("table")
.find('.' + _config.uniqueClass + ":visible"),
valuesHash = {},
isValid = true;

inputs.each(function (el) {
var inputValue = inputs[el].value;
if (typeof valuesHash[inputValue] !== "undefined") {
isValid = false;
}
valuesHash[inputValue] = el;
});
return isValid;
},

_config.message
);
}
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Plugin;

use Magento\Catalog\Controller\Adminhtml\Product\Attribute;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\DataObject;

/**
* Class Save
* @package Magento\Swatches\Controller\Adminhtml\Product\Attribute\Plugin
*/
class Validate
{
/**
* @param Attribute\Validate $subject
* @param Json $response
* @return array
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterExecute(Attribute\Validate $subject, Json $response)
{
$data = $subject->getRequest()->getPostValue();
if (isset($data['frontend_input'])) {
$dataIndex = false;
switch ($data['frontend_input']) {
case "select":
$dataIndex = "option";
break;
case "swatch_text":
$dataIndex = "optiontext";
break;
case "swatch_visual":
$dataIndex = "optionvisual";
break;
}

if ($dataIndex !== false) {
if (!$this->isUniqueAdminValues($data[$dataIndex]['value'], $data[$dataIndex]['delete'])) {
$response->setJsonData($this->createErrorResponse("The value of Admin must be unique.")->toJson());
};
}
}

return $response;
}

/**
* Throws Exception if not unique values into options
* @param array $optionsValues
* @param array $deletedOptions
* @return bool
*/
private function isUniqueAdminValues(array $optionsValues, array $deletedOptions)
{
$adminValues = array();
foreach ($optionsValues as $optionKey => $values) {
if (!(isset($deletedOptions[$optionKey]) and $deletedOptions[$optionKey] === '1')) {
$adminValues[] = reset($values);
}
}
$uniqueValues = array_unique($adminValues);
return ($uniqueValues === $adminValues);
}

/**
* @param string $message
* @return DataObject
*/
private function createErrorResponse($message)
{
$error = new DataObject();
$error->setError(true);
$error->setData(Attribute\Validate ::DEFAULT_MESSAGE_KEY, __($message));
return $error;
}
}
Loading

0 comments on commit 8241423

Please sign in to comment.