Skip to content

Commit

Permalink
MAGETWO-57607: [Backport] - Unable to save product with all unchecked…
Browse files Browse the repository at this point in the history
… values for multiple select attribute - for 2.1 #7687
  • Loading branch information
OlgaVasyltsun committed May 26, 2017
1 parent ff253a7 commit 7ec8952
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function validate($object)
$data = $object->getData($attributeCode);
if (is_array($data)) {
$object->setData($attributeCode, implode(',', array_filter($data)));
} elseif (empty($data)) {
$object->setData($attributeCode, null);
}
return parent::validate($object);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
namespace Magento\Eav\Test\Unit\Model\Entity\Attribute\Backend;

class ArrayTest extends \PHPUnit_Framework_TestCase
class ArrayBackendTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend
Expand All @@ -20,13 +20,13 @@ class ArrayTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->_attribute = $this->getMock(
'Magento\Eav\Model\Entity\Attribute',
\Magento\Eav\Model\Entity\Attribute::class,
['getAttributeCode', '__wakeup'],
[],
'',
false
);
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger = $this->getMock(\Psr\Log\LoggerInterface::class);
$this->_model = new \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend($logger);
$this->_model->setAttribute($this->_attribute);
}
Expand All @@ -37,9 +37,10 @@ protected function setUp()
public function testValidate($data)
{
$this->_attribute->expects($this->atLeastOnce())->method('getAttributeCode')->will($this->returnValue('code'));
$product = new \Magento\Framework\DataObject(['code' => $data]);
$product = new \Magento\Framework\DataObject(['code' => $data, 'empty' => '']);
$this->_model->validate($product);
$this->assertEquals('1,2,3', $product->getCode());
$this->assertEquals(null, $product->getEmpty());
}

public static function attributeValueDataProvider()
Expand Down
2 changes: 1 addition & 1 deletion app/code/Magento/Ui/view/base/web/js/form/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ define([
function beforeSave(data, url, selectorPrefix, messagesClass) {
var save = $.Deferred();

data = utils.serialize(data);
data = utils.serialize(utils.filterFormData(data));

data['form_key'] = window.FORM_KEY;

Expand Down
20 changes: 19 additions & 1 deletion app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ define([
return Select.extend({
defaults: {
size: 5,
elementTmpl: 'ui/form/element/multiselect'
elementTmpl: 'ui/form/element/multiselect',
listens: {
value: 'setDifferedFromDefault setPrepareToSendData'
}
},

/**
Expand All @@ -38,6 +41,21 @@ define([
return _.isString(value) ? value.split(',') : value;
},

/**
* Sets the prepared data to dataSource
* by path, where key is component link to dataSource with
* suffix "-prepared-for-send".
*
* @param {Array} data - current component value
*/
setPrepareToSendData: function (data) {
if (!data.length) {
data = '';
}

this.source.set(this.dataScope + '-prepared-for-send', data);
},

/**
* @inheritdoc
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/
namespace Magento\Catalog\Controller\Adminhtml;

use Magento\Catalog\Model\ProductRepository;

/**
* @magentoAppArea adminhtml
*/
Expand All @@ -27,7 +29,7 @@ public function testSaveActionWithDangerRequest()
public function testSaveActionAndNew()
{
$this->getRequest()->setPostValue(['back' => 'new']);
$repository = $this->_objectManager->create('Magento\Catalog\Model\ProductRepository');
$repository = $this->_objectManager->create(ProductRepository::class);
$product = $repository->get('simple');
$this->dispatch('backend/catalog/product/save/id/' . $product->getEntityId());
$this->assertRedirect($this->stringStartsWith('http://localhost/index.php/backend/catalog/product/new/'));
Expand All @@ -43,7 +45,7 @@ public function testSaveActionAndNew()
public function testSaveActionAndDuplicate()
{
$this->getRequest()->setPostValue(['back' => 'duplicate']);
$repository = $this->_objectManager->create('Magento\Catalog\Model\ProductRepository');
$repository = $this->_objectManager->create(ProductRepository::class);
$product = $repository->get('simple');
$this->dispatch('backend/catalog/product/save/id/' . $product->getEntityId());
$this->assertRedirect($this->stringStartsWith('http://localhost/index.php/backend/catalog/product/edit/'));
Expand Down Expand Up @@ -100,7 +102,7 @@ public function testIndexAction()
*/
public function testEditAction()
{
$repository = $this->_objectManager->create('Magento\Catalog\Model\ProductRepository');
$repository = $this->_objectManager->create(ProductRepository::class);
$product = $repository->get('simple');
$this->dispatch('backend/catalog/product/edit/id/' . $product->getEntityId());
$body = $this->getResponse()->getBody();
Expand All @@ -119,4 +121,31 @@ public function testEditAction()
'"Save & Duplicate" button isn\'t present on Edit Product page'
);
}

/**
* Tests Validate product action.
*
* @magentoDataFixture Magento/Catalog/_files/products_with_multiselect_attribute.php
*
* @return void
*/
public function testValidateAction()
{
$expectedResult = json_encode(['error' => false]);

$repository = $this->_objectManager->create(ProductRepository::class);
$product = $repository->get('simple_ms_2');
$data = $product->getData();
unset($data['multiselect_attribute']);

$this->getRequest()->setPostValue(['product' => $data]);
$this->dispatch('backend/catalog/product/validate');
$response = $this->getResponse()->getBody();

$this->assertJsonStringEqualsJsonString(
$expectedResult,
$response,
'Validate action returned incorrect result.'
);
}
}
26 changes: 26 additions & 0 deletions lib/web/mage/utils/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,32 @@ define([
}

return formData;
},

/**
* Filters data object. Finds properties with suffix
* and sets their values to properties with the same name without suffix.
*
* @param {Object} data - The data object that should be filtered
* @param {String} suffix - The string by which data object should be filtered
* @param {String} separator - The string that is separator between property and suffix
*
* @returns {Object} Filtered data object
*/
filterFormData: function (data, suffix, separator) {
data = data || {};
suffix = suffix || 'prepared-for-send';
separator = separator || '-';
_.each(data, function (value, key) {
if (_.isObject(value) && !value.length) {
this.filterFormData(value, suffix, separator)
} else if (_.isString(key) && ~key.indexOf(suffix)) {
data[key.split(separator)[0]] = value;
delete data[key];
}
}, this);

return data;
}
};
});

0 comments on commit 7ec8952

Please sign in to comment.