Skip to content

Commit 6ce2b5f

Browse files
author
Sergey Semenov
committed
MAGETWO-42994: Customer custom attribute is not validated on frontend
1 parent f553937 commit 6ce2b5f

File tree

5 files changed

+152
-45
lines changed

5 files changed

+152
-45
lines changed

app/code/Magento/Customer/Helper/Address.php

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ class Address extends \Magento\Framework\App\Helper\AbstractHelper
7171
/** @var \Magento\Store\Model\StoreManagerInterface */
7272
protected $_storeManager;
7373

74-
/** @var CustomerMetadataInterface */
74+
/**
75+
* @var CustomerMetadataInterface
76+
*
77+
* @deprecated
78+
*/
7579
protected $_customerMetadataService;
7680

7781
/** @var AddressMetadataInterface */
@@ -243,19 +247,8 @@ public function getAttributeValidationClass($attributeCode)
243247
$attribute = isset($this->_attributes[$attributeCode])
244248
? $this->_attributes[$attributeCode]
245249
: $this->_addressMetadataService->getAttributeMetadata($attributeCode);
246-
$class = $attribute ? $attribute->getFrontendClass() : '';
247-
if (in_array($attributeCode, ['firstname', 'middlename', 'lastname', 'prefix', 'suffix', 'taxvat'])) {
248-
if ($class && !$attribute->isVisible()) {
249-
// address attribute is not visible thus its validation rules are not applied
250-
$class = '';
251-
}
252250

253-
/** @var $customerAttribute AttributeMetadataInterface */
254-
$customerAttribute = $this->_customerMetadataService->getAttributeMetadata($attributeCode);
255-
$class .= $customerAttribute &&
256-
$customerAttribute->isVisible() ? $customerAttribute->getFrontendClass() : '';
257-
$class = implode(' ', array_unique(array_filter(explode(' ', $class))));
258-
}
251+
$class = $attribute ? $attribute->getFrontendClass() : '';
259252
} catch (NoSuchEntityException $e) {
260253
// the attribute does not exist so just return an empty string
261254
}

app/code/Magento/Customer/Test/Unit/Helper/AddressTest.php

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -147,39 +147,33 @@ public function testGetConfigCanShowConfig()
147147
$this->assertTrue($this->helper->canShowConfig('key2'));
148148
}
149149

150-
/**
151-
* @param $attrCode
152-
* @param $attrClass
153-
* @param $customAttrClass
154-
* @param $result
155-
* @dataProvider getAttributeValidationClassDataProvider
156-
*/
157-
public function testGetAttributeValidationClass($attrCode, $attrClass, $customAttrClass, $result)
150+
public function testGetAttributeValidationClass()
158151
{
159-
$attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')->getMock();
160-
$attributeMock->expects($this->any())->method('getFrontendClass')->will($this->returnValue($attrClass));
152+
$attributeCode = 'attr_code';
153+
$attributeClass = 'Attribute_Class';
161154

162-
$customAttrMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')->getMock();
163-
$customAttrMock->expects($this->any())->method('isVisible')->will($this->returnValue(true));
164-
$customAttrMock->expects($this->any())->method('getFrontendClass')->will($this->returnValue($customAttrClass));
165-
166-
$this->customerMetadataService->expects($this->any())
167-
->method('getAttributeMetadata')
168-
->will($this->returnValue($customAttrMock));
155+
$attributeMock = $this->getMockBuilder('Magento\Customer\Api\Data\AttributeMetadataInterface')
156+
->getMockForAbstractClass();
157+
$attributeMock->expects($this->once())
158+
->method('getFrontendClass')
159+
->willReturn($attributeClass);
169160

170161
$this->addressMetadataService->expects($this->any())
171162
->method('getAttributeMetadata')
172-
->will($this->returnValue($attributeMock));
163+
->willReturn($attributeMock);
173164

174-
$this->assertEquals($result, $this->helper->getAttributeValidationClass($attrCode));
165+
$this->assertEquals($attributeClass, $this->helper->getAttributeValidationClass($attributeCode));
175166
}
176167

177-
public function getAttributeValidationClassDataProvider()
168+
public function testGetAttributeValidationClassWithNoAttribute()
178169
{
179-
return [
180-
['attr_code', 'Attribute_Class', '', 'Attribute_Class'],
181-
['firstname', 'Attribute_Class', 'Attribute2_Class', 'Attribute2_Class'],
182-
];
170+
$attrCode = 'attr_code';
171+
172+
$this->addressMetadataService->expects($this->any())
173+
->method('getAttributeMetadata')
174+
->willReturn(null);
175+
176+
$this->assertEquals('', $this->helper->getAttributeValidationClass($attrCode));
183177
}
184178

185179
/**

app/code/Magento/Eav/Model/Entity/Attribute/Frontend/AbstractFrontend.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,13 @@ public function getClass()
155155
if ($inputRuleClass) {
156156
$out[] = $inputRuleClass;
157157
}
158-
if (!empty($out)) {
159-
$out = implode(' ', $out);
160-
} else {
161-
$out = '';
158+
159+
$textLengthValidateClasses = $this->getTextLengthValidateClasses();
160+
if (!empty($textLengthValidateClasses)) {
161+
$out[] = implode(' ', $textLengthValidateClasses);
162162
}
163+
164+
$out = !empty($out) ? implode(' ', $out) : '';
163165
return $out;
164166
}
165167

@@ -197,6 +199,29 @@ protected function _getInputValidateClass()
197199
return $class;
198200
}
199201

202+
/**
203+
* Retrieve validation classes by min_text_length and max_text_length rules
204+
*
205+
* @return array
206+
*/
207+
private function getTextLengthValidateClasses()
208+
{
209+
$classes = [];
210+
211+
$validateRules = $this->getAttribute()->getValidateRules();
212+
if (!empty($validateRules['min_text_length'])) {
213+
$classes[] = 'minimum-length-' . $validateRules['min_text_length'];
214+
}
215+
if (!empty($validateRules['max_text_length'])) {
216+
$classes[] = 'maximum-length-' . $validateRules['max_text_length'];
217+
}
218+
if (!empty($classes)) {
219+
$classes[] = 'validate-length';
220+
}
221+
222+
return $classes;
223+
}
224+
200225
/**
201226
* Reireive config field
202227
*
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Eav\Test\Unit\Model\Entity\Attribute\Frontend;
7+
8+
use Magento\Eav\Model\Entity\Attribute\Frontend\DefaultFrontend;
9+
10+
class DefaultFrontendTest extends \PHPUnit_Framework_TestCase
11+
{
12+
/**
13+
* @var DefaultFrontend
14+
*/
15+
protected $model;
16+
17+
/**
18+
* @var \Magento\Eav\Model\Entity\Attribute\Source\BooleanFactory|\PHPUnit_Framework_MockObject_MockObject
19+
*/
20+
protected $booleanFactory;
21+
22+
protected function setUp()
23+
{
24+
$this->booleanFactory = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Source\BooleanFactory')
25+
->disableOriginalConstructor()
26+
->getMock();
27+
28+
$this->model = new DefaultFrontend(
29+
$this->booleanFactory
30+
);
31+
}
32+
33+
public function testGetClassEmpty()
34+
{
35+
/** @var \PHPUnit_Framework_MockObject_MockObject $attributeMock */
36+
$attributeMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
37+
->disableOriginalConstructor()
38+
->setMethods([
39+
'getIsRequired',
40+
'getFrontendClass',
41+
'getValidateRules',
42+
])
43+
->getMock();
44+
$attributeMock->expects($this->once())
45+
->method('getIsRequired')
46+
->willReturn(false);
47+
$attributeMock->expects($this->once())
48+
->method('getFrontendClass')
49+
->willReturn('');
50+
$attributeMock->expects($this->exactly(2))
51+
->method('getValidateRules')
52+
->willReturn('');
53+
54+
$this->model->setAttribute($attributeMock);
55+
$this->assertEmpty($this->model->getClass());
56+
}
57+
58+
public function testGetClass()
59+
{
60+
/** @var \PHPUnit_Framework_MockObject_MockObject $attributeMock */
61+
$attributeMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
62+
->disableOriginalConstructor()
63+
->setMethods([
64+
'getIsRequired',
65+
'getFrontendClass',
66+
'getValidateRules',
67+
])
68+
->getMock();
69+
$attributeMock->expects($this->once())
70+
->method('getIsRequired')
71+
->willReturn(true);
72+
$attributeMock->expects($this->once())
73+
->method('getFrontendClass')
74+
->willReturn('');
75+
$attributeMock->expects($this->exactly(2))
76+
->method('getValidateRules')
77+
->willReturn([
78+
'input_validation' => 'alphanumeric',
79+
'min_text_length' => 1,
80+
'max_text_length' => 2,
81+
]);
82+
83+
$this->model->setAttribute($attributeMock);
84+
$result = $this->model->getClass();
85+
86+
$this->assertContains('validate-alphanum', $result);
87+
$this->assertContains('minimum-length-1', $result);
88+
$this->assertContains('maximum-length-2', $result);
89+
$this->assertContains('validate-length', $result);
90+
}
91+
}

lib/web/mage/validation.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,18 +1137,22 @@
11371137
$.each(elm.className.split(' '), function (index, name) {
11381138
if (name.match(reMax) && result) {
11391139
length = name.split('-')[2];
1140-
validator.attrLength = length;
11411140
result = (v.length <= length);
1141+
validator.validateMessage = $.mage.__(
1142+
"Please enter less or equal than %1 symbols."
1143+
).replace('%1', length);
11421144
}
1143-
if (name.match(reMin) && result && $.mage.isEmpty(v)) {
1145+
if (name.match(reMin) && result && !$.mage.isEmpty(v)) {
11441146
length = name.split('-')[2];
11451147
result = v.length >= length;
1148+
validator.validateMessage = $.mage.__(
1149+
"Please enter more or equal than %1 symbols."
1150+
).replace('%1', length);
11461151
}
11471152
});
11481153
return result;
11491154
}, function () {
1150-
return $.mage.__("Maximum length of this field must be equal or less than %1 symbols.")
1151-
.replace('%1', this.attrLength);
1155+
return this.validateMessage;
11521156
}
11531157
],
11541158
'required-entry': [

0 commit comments

Comments
 (0)