Skip to content

Commit 70aaafb

Browse files
author
Oleksii Korshenko
committed
MAGETWO-52616: Bug Fixes Contribution
Merge remote-tracking branch 'origin/MAGETWO-51234-Custom-Attributes-Validation' into pull-request
2 parents 3c76c91 + 1146a89 commit 70aaafb

File tree

13 files changed

+616
-123
lines changed

13 files changed

+616
-123
lines changed

app/code/Magento/Eav/Model/EavCustomAttributeTypeLocator.php

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use Magento\Eav\Api\AttributeRepositoryInterface;
1010
use Magento\Framework\Exception\NoSuchEntityException;
1111
use Magento\Framework\Webapi\CustomAttributeTypeLocatorInterface;
12+
use Magento\Eav\Model\EavCustomAttributeTypeLocator\ComplexType as ComplexTypeLocator;
13+
use Magento\Eav\Model\EavCustomAttributeTypeLocator\SimpleType as SimpleTypeLocator;
14+
use Magento\Framework\Reflection\TypeProcessor;
1215

1316
/**
1417
* Class to locate types for Eav custom attributes
@@ -20,11 +23,6 @@ class EavCustomAttributeTypeLocator implements CustomAttributeTypeLocatorInterfa
2023
*/
2124
private $attributeRepository;
2225

23-
/**
24-
* @var \Magento\Framework\Stdlib\StringUtils
25-
*/
26-
private $stringUtility;
27-
2826
/**
2927
* @var array
3028
*/
@@ -35,9 +33,20 @@ class EavCustomAttributeTypeLocator implements CustomAttributeTypeLocatorInterfa
3533
*/
3634
private $serviceBackendModelDataInterfaceMap;
3735

36+
/**
37+
* @var ComplexTypeLocator
38+
*/
39+
private $complexTypeLocator;
40+
41+
/**
42+
* @var SimpleTypeLocator
43+
*/
44+
private $simpleTypeLocator;
45+
3846
/**
3947
* Initialize EavCustomAttributeTypeLocator
4048
*
49+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
4150
* @codeCoverageIgnore
4251
* @param AttributeRepositoryInterface $attributeRepository Attribute repository service
4352
* @param \Magento\Framework\Stdlib\StringUtils $stringUtility
@@ -66,44 +75,33 @@ public function __construct(
6675
array $serviceBackendModelDataInterfaceMap = []
6776
) {
6877
$this->attributeRepository = $attributeRepository;
69-
$this->stringUtility = $stringUtility;
7078
$this->serviceEntityTypeMap = $serviceEntityTypeMap;
7179
$this->serviceBackendModelDataInterfaceMap = $serviceBackendModelDataInterfaceMap;
7280
}
7381

7482
/**
7583
* {@inheritdoc}
76-
* @SuppressWarnings(PHPMD.NPathComplexity)
7784
*/
7885
public function getType($attributeCode, $serviceClass)
7986
{
8087
if (!$serviceClass || !$attributeCode || !isset($this->serviceEntityTypeMap[$serviceClass])
8188
|| !isset($this->serviceBackendModelDataInterfaceMap[$serviceClass])
8289
) {
83-
return null;
90+
return TypeProcessor::ANY_TYPE;
8491
}
8592

8693
try {
8794
$attribute = $this->attributeRepository->get($this->serviceEntityTypeMap[$serviceClass], $attributeCode);
88-
$backendModel = $attribute->getBackendModel();
8995
} catch (NoSuchEntityException $e) {
90-
return null;
91-
}
92-
93-
//If empty backend model, check if it can be derived
94-
if (empty($backendModel)) {
95-
$backendModelClass = sprintf(
96-
'Magento\Eav\Model\Attribute\Data\%s',
97-
$this->stringUtility->upperCaseWords($attribute->getFrontendInput())
98-
);
99-
$backendModel = class_exists($backendModelClass) ? $backendModelClass : null;
96+
return TypeProcessor::ANY_TYPE;
10097
}
10198

102-
$dataInterface = isset($this->serviceBackendModelDataInterfaceMap[$serviceClass][$backendModel])
103-
? $this->serviceBackendModelDataInterfaceMap[$serviceClass][$backendModel]
104-
: null;
105-
106-
return $dataInterface;
99+
$dataInterface = $this->getComplexTypeLocator()->getType(
100+
$attribute,
101+
$serviceClass,
102+
$this->serviceBackendModelDataInterfaceMap
103+
);
104+
return $dataInterface ?: $this->getSimpleTypeLocator()->getType($attribute);
107105
}
108106

109107
/**
@@ -123,4 +121,32 @@ public function getAllServiceDataInterfaces()
123121
}
124122
return $dataInterfaceArray;
125123
}
124+
125+
/**
126+
* Get complex type locator instance
127+
*
128+
* @return ComplexTypeLocator
129+
* @deprecated
130+
*/
131+
private function getComplexTypeLocator()
132+
{
133+
if (!$this->complexTypeLocator instanceof ComplexTypeLocator) {
134+
return \Magento\Framework\App\ObjectManager::getInstance()->get(ComplexTypeLocator::class);
135+
}
136+
return $this->complexTypeLocator;
137+
}
138+
139+
/**
140+
* Get simple type locator instance
141+
*
142+
* @return SimpleTypeLocator
143+
* @deprecated
144+
*/
145+
private function getSimpleTypeLocator()
146+
{
147+
if (!$this->simpleTypeLocator instanceof SimpleTypeLocator) {
148+
return \Magento\Framework\App\ObjectManager::getInstance()->get(SimpleTypeLocator::class);
149+
}
150+
return $this->simpleTypeLocator;
151+
}
126152
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Eav\Model\EavCustomAttributeTypeLocator;
8+
9+
/**
10+
* Class to locate complex types for EAV custom attributes
11+
*/
12+
class ComplexType
13+
{
14+
/**
15+
* @var \Magento\Framework\Stdlib\StringUtils
16+
*/
17+
private $stringUtility;
18+
19+
/**
20+
* Initialize dependencies
21+
*
22+
* @codeCoverageIgnore
23+
* @param \Magento\Framework\Stdlib\StringUtils $stringUtility
24+
*/
25+
public function __construct(
26+
\Magento\Framework\Stdlib\StringUtils $stringUtility
27+
) {
28+
$this->stringUtility = $stringUtility;
29+
}
30+
31+
/**
32+
* Get attribute type based on its backend model.
33+
*
34+
* @param \Magento\Eav\Api\Data\AttributeInterface $attribute
35+
* @param string $serviceClass
36+
* @param $serviceBackendModelDataInterfaceMap array
37+
* @return string|null
38+
*/
39+
public function getType($attribute, $serviceClass, $serviceBackendModelDataInterfaceMap)
40+
{
41+
$backendModel = $attribute->getBackendModel();
42+
//If empty backend model, check if it can be derived
43+
if (empty($backendModel)) {
44+
$backendModelClass = sprintf(
45+
'Magento\Eav\Model\Attribute\Data\%s',
46+
$this->stringUtility->upperCaseWords($attribute->getFrontendInput())
47+
);
48+
$backendModel = class_exists($backendModelClass) ? $backendModelClass : null;
49+
}
50+
51+
$dataInterface = isset($serviceBackendModelDataInterfaceMap[$serviceClass][$backendModel])
52+
? $serviceBackendModelDataInterfaceMap[$serviceClass][$backendModel]
53+
: null;
54+
55+
return $dataInterface;
56+
}
57+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Eav\Model\EavCustomAttributeTypeLocator;
8+
9+
use Magento\Framework\Reflection\TypeProcessor;
10+
11+
/**
12+
* Class to locate simple types for Eav custom attributes
13+
*/
14+
class SimpleType
15+
{
16+
/**
17+
* List of attributes, type of which cannot be identified reliably. We do not validate these attributes.
18+
*
19+
* @var string[]
20+
*/
21+
private $anyTypeAttributes = ['quantity_and_stock_status'];
22+
23+
/**
24+
* Get attribute type based on its frontend input and backend type.
25+
*
26+
* @param \Magento\Eav\Api\Data\AttributeInterface $attribute
27+
* @return string
28+
*/
29+
public function getType($attribute)
30+
{
31+
if (in_array($attribute->getAttributeCode(), $this->anyTypeAttributes)) {
32+
return TypeProcessor::NORMALIZED_ANY_TYPE;
33+
}
34+
$frontendInput = $attribute->getFrontendInput();
35+
$backendType = $attribute->getBackendType();
36+
$backendTypeMap = [
37+
'static' => TypeProcessor::NORMALIZED_ANY_TYPE,
38+
'int' => TypeProcessor::NORMALIZED_INT_TYPE,
39+
'text' => TypeProcessor::NORMALIZED_STRING_TYPE,
40+
'varchar' => TypeProcessor::NORMALIZED_STRING_TYPE,
41+
'datetime' => TypeProcessor::NORMALIZED_STRING_TYPE,
42+
'decimal' => TypeProcessor::NORMALIZED_DOUBLE_TYPE,
43+
];
44+
$arrayFrontendInputs = ['multiselect'];
45+
$type = $backendTypeMap[$backendType];
46+
if (in_array($frontendInput, $arrayFrontendInputs)) {
47+
$type .= '[]';
48+
}
49+
return $type;
50+
}
51+
}

app/code/Magento/Eav/Test/Unit/Model/EavCustomAttributeTypeLocatorTest.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
use Magento\Eav\Api\AttributeRepositoryInterface;
1212
use Magento\Eav\Model\EavCustomAttributeTypeLocator;
13+
use Magento\Eav\Model\EavCustomAttributeTypeLocator\SimpleType as SimpleTypeLocator;
14+
use Magento\Eav\Model\EavCustomAttributeTypeLocator\ComplexType as ComplexTypeLocator;
1315

1416
/**
1517
* Unit test class for \Magento\Eav\Model\EavCustomAttributeTypeLocator
@@ -62,15 +64,28 @@ public function testGetType(
6264
->expects($this->any())
6365
->method('get')
6466
->willReturn($attributeRepositoryResponse);
65-
66-
67+
6768
$this->eavCustomAttributeTypeLocator = new EavCustomAttributeTypeLocator(
6869
$this->attributeRepository,
6970
$stringUtility,
7071
$serviceEntityTypeMapData,
7172
$serviceBackendModelDataInterfaceMapData
7273
);
7374

75+
$simpleTypeLocator = new SimpleTypeLocator();
76+
// Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793)
77+
$reflection = new \ReflectionClass(get_class($this->eavCustomAttributeTypeLocator));
78+
$reflectionProperty = $reflection->getProperty('simpleTypeLocator');
79+
$reflectionProperty->setAccessible(true);
80+
$reflectionProperty->setValue($this->eavCustomAttributeTypeLocator, $simpleTypeLocator);
81+
82+
$complexTypeLocator = new ComplexTypeLocator($stringUtility);
83+
// Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793)
84+
$reflection = new \ReflectionClass(get_class($this->eavCustomAttributeTypeLocator));
85+
$reflectionProperty = $reflection->getProperty('complexTypeLocator');
86+
$reflectionProperty->setAccessible(true);
87+
$reflectionProperty->setValue($this->eavCustomAttributeTypeLocator, $complexTypeLocator);
88+
7489
$type = $this->eavCustomAttributeTypeLocator->getType($attributeCode, $serviceClass);
7590

7691
$this->assertEquals($expected, $type, 'Expected: ' . $expected . 'but got: ' . $type);
@@ -137,7 +152,7 @@ public function getTypeDataProvider()
137152
'stringUtility' => $stringUtility,
138153
'serviceEntityTypeMapData' => [$serviceInterface => $eavEntityType],
139154
'serviceBackendModelDataInterfaceMapData' => $serviceBackendModelDataInterfaceMapData,
140-
'expected' => null
155+
'expected' => 'mixed'
141156
],
142157
[
143158
'attributeCode' => 'media_galley',
@@ -146,7 +161,7 @@ public function getTypeDataProvider()
146161
'stringUtility' => $stringUtility,
147162
'serviceEntityTypeMapData' => [$serviceInterface => $eavEntityType],
148163
'serviceBackendModelDataInterfaceMapData' => $serviceBackendModelDataInterfaceMapData,
149-
'expected' => null
164+
'expected' => 'mixed'
150165
],
151166
[
152167
'attributeCode' => 'media_galley',
@@ -155,7 +170,7 @@ public function getTypeDataProvider()
155170
'stringUtility' => $stringUtility,
156171
'serviceEntityTypeMapData' => [],
157172
'serviceBackendModelDataInterfaceMapData' => [],
158-
'expected' => null
173+
'expected' => 'mixed'
159174
],
160175
[
161176
'attributeCode' => 'media_galley',
@@ -164,7 +179,7 @@ public function getTypeDataProvider()
164179
'stringUtility' => $stringUtility,
165180
'serviceEntityTypeMapData' => [$serviceInterface => $eavEntityType],
166181
'serviceBackendModelDataInterfaceMapData' => [],
167-
'expected' => null
182+
'expected' => 'mixed'
168183
],
169184
[
170185
'attributeCode' => 'image',
@@ -198,7 +213,8 @@ public function testGetTypeIfAttributeDoesNotExist()
198213
[]
199214
);
200215

201-
$this->assertNull(
216+
$this->assertEquals(
217+
'mixed',
202218
$this->eavCustomAttributeTypeLocator->getType('media_galley', 'Magento\Catalog\Api\Data\ProductInterface')
203219
);
204220
}

0 commit comments

Comments
 (0)