|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* TechDivision\Import\Subjects\AbstractSubject |
|
5
|
|
|
* |
|
6
|
|
|
* NOTICE OF LICENSE |
|
7
|
|
|
* |
|
8
|
|
|
* This source file is subject to the Open Software License (OSL 3.0) |
|
9
|
|
|
* that is available through the world-wide-web at this URL: |
|
10
|
|
|
* http://opensource.org/licenses/osl-3.0.php |
|
11
|
|
|
* |
|
12
|
|
|
* PHP version 5 |
|
13
|
|
|
* |
|
14
|
|
|
* @author Tim Wagner <[email protected]> |
|
15
|
|
|
* @copyright 2016 TechDivision GmbH <[email protected]> |
|
16
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
|
17
|
|
|
* @link https://github.com/techdivision/import |
|
18
|
|
|
* @link http://www.techdivision.com |
|
19
|
|
|
*/ |
|
20
|
|
|
|
|
21
|
|
|
namespace TechDivision\Import\Subjects; |
|
22
|
|
|
|
|
23
|
|
|
use TechDivision\Import\Utils\MemberNames; |
|
24
|
|
|
use TechDivision\Import\Utils\RegistryKeys; |
|
25
|
|
|
use TechDivision\Import\Utils\BackendTypeKeys; |
|
26
|
|
|
use TechDivision\Import\Utils\EntityTypeCodes; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* An abstract EAV subject implementation. |
|
30
|
|
|
* |
|
31
|
|
|
* @author Tim Wagner <[email protected]> |
|
32
|
|
|
* @copyright 2016 TechDivision GmbH <[email protected]> |
|
33
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
|
34
|
|
|
* @link https://github.com/techdivision/import |
|
35
|
|
|
* @link http://www.techdivision.com |
|
36
|
|
|
*/ |
|
37
|
|
|
abstract class AbstractEavSubject extends AbstractSubject implements EavSubjectInterface |
|
38
|
|
|
{ |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* The available EAV attributes, grouped by their attribute set and the attribute set name as keys. |
|
42
|
|
|
* |
|
43
|
|
|
* @var array |
|
44
|
|
|
*/ |
|
45
|
|
|
protected $attributes = array(); |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* The available user defined EAV attributes, grouped by their entity type. |
|
49
|
|
|
* |
|
50
|
|
|
* @var array |
|
51
|
|
|
*/ |
|
52
|
|
|
protected $userDefinedAttributes = array(); |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* The attribute set of the entity that has to be created. |
|
56
|
|
|
* |
|
57
|
|
|
* @var array |
|
58
|
|
|
*/ |
|
59
|
|
|
protected $attributeSet = array(); |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* The available EAV attribute sets. |
|
63
|
|
|
* |
|
64
|
|
|
* @var array |
|
65
|
|
|
*/ |
|
66
|
|
|
protected $attributeSets = array(); |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* The mapping for the supported backend types (for the EAV entity) => persist methods. |
|
70
|
|
|
* |
|
71
|
|
|
* @var array |
|
72
|
|
|
*/ |
|
73
|
|
|
protected $backendTypes = array( |
|
74
|
|
|
BackendTypeKeys::BACKEND_TYPE_DATETIME => array('persistDatetimeAttribute', 'loadDatetimeAttribute', 'deleteDatetimeAttribute'), |
|
75
|
|
|
BackendTypeKeys::BACKEND_TYPE_DECIMAL => array('persistDecimalAttribute', 'loadDecimalAttribute', 'deleteDecimalAttribute'), |
|
76
|
|
|
BackendTypeKeys::BACKEND_TYPE_INT => array('persistIntAttribute', 'loadIntAttribute', 'deleteIntAttribute'), |
|
77
|
|
|
BackendTypeKeys::BACKEND_TYPE_TEXT => array('persistTextAttribute', 'loadTextAttribute', 'deleteTextAttribute'), |
|
78
|
|
|
BackendTypeKeys::BACKEND_TYPE_VARCHAR => array('persistVarcharAttribute', 'loadVarcharAttribute', 'deleteVarcharAttribute') |
|
79
|
|
|
); |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* The mappings for the entity type code to attribute set. |
|
83
|
|
|
* |
|
84
|
|
|
* @var array |
|
85
|
|
|
*/ |
|
86
|
|
|
protected $entityTypeCodeToAttributeSetMappings = array( |
|
87
|
|
|
EntityTypeCodes::CATALOG_PRODUCT => EntityTypeCodes::CATALOG_PRODUCT, |
|
88
|
|
|
EntityTypeCodes::CATALOG_PRODUCT_PRICE => EntityTypeCodes::CATALOG_PRODUCT, |
|
89
|
|
|
EntityTypeCodes::CATALOG_PRODUCT_INVENTORY => EntityTypeCodes::CATALOG_PRODUCT, |
|
90
|
|
|
EntityTypeCodes::CATALOG_CATEGORY => EntityTypeCodes::CATALOG_CATEGORY, |
|
91
|
|
|
EntityTypeCodes::EAV_ATTRIBUTE => EntityTypeCodes::EAV_ATTRIBUTE, |
|
92
|
|
|
EntityTypeCodes::NONE => EntityTypeCodes::NONE |
|
93
|
|
|
); |
|
94
|
|
|
|
|
95
|
|
|
/** |
|
96
|
|
|
* The default mappings for the user defined attributes, based on the attributes frontend input type. |
|
97
|
|
|
* |
|
98
|
|
|
* @var array |
|
99
|
|
|
*/ |
|
100
|
|
|
protected $defaultFrontendInputCallbackMappings = array(); |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* Return's the default callback frontend input mappings for the user defined attributes. |
|
104
|
|
|
* |
|
105
|
|
|
* @return array The default frontend input callback mappings |
|
106
|
|
|
*/ |
|
107
|
22 |
|
public function getDefaultFrontendInputCallbackMappings() |
|
108
|
|
|
{ |
|
109
|
22 |
|
return $this->defaultFrontendInputCallbackMappings; |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
/** |
|
113
|
|
|
* Intializes the previously loaded global data for exactly one bunch. |
|
114
|
|
|
* |
|
115
|
|
|
* @param string $serial The serial of the actual import |
|
116
|
|
|
* |
|
117
|
|
|
* @return void |
|
118
|
|
|
*/ |
|
119
|
22 |
|
public function setUp($serial) |
|
120
|
|
|
{ |
|
121
|
|
|
|
|
122
|
|
|
// load the status of the actual import |
|
123
|
22 |
|
$status = $this->getRegistryProcessor()->getAttribute($serial); |
|
124
|
|
|
|
|
125
|
|
|
// load the global data we've prepared initially |
|
126
|
22 |
|
$this->attributes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::EAV_ATTRIBUTES]; |
|
127
|
22 |
|
$this->attributeSets = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::ATTRIBUTE_SETS]; |
|
128
|
22 |
|
$this->userDefinedAttributes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::EAV_USER_DEFINED_ATTRIBUTES]; |
|
129
|
|
|
|
|
130
|
|
|
// load the default frontend callback mappings from the child instance and merge with the one from the configuration |
|
131
|
22 |
|
$defaultFrontendInputCallbackMappings = $this->getDefaultFrontendInputCallbackMappings(); |
|
132
|
|
|
|
|
133
|
|
|
// merge the default mappings with the one's found in the configuration |
|
134
|
22 |
|
foreach ($this->getConfiguration()->getFrontendInputCallbacks() as $frontendInputCallbackMappings) { |
|
135
|
|
|
foreach ($frontendInputCallbackMappings as $frontendInput => $frontentInputMappings) { |
|
136
|
|
|
$defaultFrontendInputCallbackMappings[$frontendInput] = $frontentInputMappings; |
|
137
|
|
|
} |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
// load the user defined attributes and add the callback mappings |
|
141
|
22 |
|
foreach ($this->getEavUserDefinedAttributes() as $eavAttribute) { |
|
142
|
|
|
// load attribute code and frontend input type |
|
143
|
1 |
|
$attributeCode = $eavAttribute[MemberNames::ATTRIBUTE_CODE]; |
|
144
|
1 |
|
$frontendInput = $eavAttribute[MemberNames::FRONTEND_INPUT]; |
|
145
|
|
|
|
|
146
|
|
|
// query whether or not the array for the mappings has been initialized |
|
147
|
1 |
|
if (!isset($this->callbackMappings[$attributeCode])) { |
|
148
|
1 |
|
$this->callbackMappings[$attributeCode] = array(); |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
// set the appropriate callback mapping for the attributes input type |
|
152
|
1 |
|
if (isset($defaultFrontendInputCallbackMappings[$frontendInput])) { |
|
153
|
1 |
|
foreach ($defaultFrontendInputCallbackMappings[$frontendInput] as $defaultFrontendInputCallbackMapping) { |
|
154
|
1 |
|
$this->callbackMappings[$attributeCode][] = $defaultFrontendInputCallbackMapping; |
|
155
|
|
|
} |
|
156
|
|
|
} |
|
157
|
|
|
} |
|
158
|
|
|
|
|
159
|
|
|
// prepare the callbacks |
|
160
|
22 |
|
parent::setUp($serial); |
|
161
|
22 |
|
} |
|
162
|
|
|
|
|
163
|
|
|
/** |
|
164
|
|
|
* Return's mapping for the supported backend types (for the product entity) => persist methods. |
|
165
|
|
|
* |
|
166
|
|
|
* @return array The mapping for the supported backend types |
|
167
|
|
|
*/ |
|
168
|
1 |
|
public function getBackendTypes() |
|
169
|
|
|
{ |
|
170
|
1 |
|
return $this->backendTypes; |
|
171
|
|
|
} |
|
172
|
|
|
|
|
173
|
|
|
/** |
|
174
|
|
|
* Set's the attribute set of the product that has to be created. |
|
175
|
|
|
* |
|
176
|
|
|
* @param array $attributeSet The attribute set |
|
177
|
|
|
* |
|
178
|
|
|
* @return void |
|
179
|
|
|
*/ |
|
180
|
5 |
|
public function setAttributeSet(array $attributeSet) |
|
181
|
|
|
{ |
|
182
|
5 |
|
$this->attributeSet = $attributeSet; |
|
183
|
5 |
|
} |
|
184
|
|
|
|
|
185
|
|
|
/** |
|
186
|
|
|
* Return's the attribute set of the product that has to be created. |
|
187
|
|
|
* |
|
188
|
|
|
* @return array The attribute set |
|
189
|
|
|
*/ |
|
190
|
1 |
|
public function getAttributeSet() |
|
191
|
|
|
{ |
|
192
|
1 |
|
return $this->attributeSet; |
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
/** |
|
196
|
|
|
* Cast's the passed value based on the backend type information. |
|
197
|
|
|
* |
|
198
|
|
|
* @param string $backendType The backend type to cast to |
|
199
|
|
|
* @param mixed $value The value to be casted |
|
200
|
|
|
* |
|
201
|
|
|
* @return mixed The casted value |
|
202
|
|
|
*/ |
|
203
|
9 |
|
public function castValueByBackendType($backendType, $value) |
|
204
|
|
|
{ |
|
205
|
|
|
|
|
206
|
|
|
// cast the value to a valid timestamp |
|
207
|
9 |
|
if ($backendType === BackendTypeKeys::BACKEND_TYPE_DATETIME) { |
|
208
|
2 |
|
return \DateTime::createFromFormat($this->getSourceDateFormat(), $value)->format('Y-m-d H:i:s'); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
// cast the value to a float value |
|
212
|
7 |
|
if ($backendType === BackendTypeKeys::BACKEND_TYPE_FLOAT) { |
|
213
|
2 |
|
return (float) $value; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
// cast the value to an integer |
|
217
|
5 |
|
if ($backendType === BackendTypeKeys::BACKEND_TYPE_INT) { |
|
218
|
3 |
|
return (int) $value; |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
|
|
// we don't need to cast strings |
|
222
|
2 |
|
return $value; |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
/** |
|
226
|
|
|
* Return's the entity type code to be used. |
|
227
|
|
|
* |
|
228
|
|
|
* @return string The entity type code to be used |
|
229
|
|
|
*/ |
|
230
|
22 |
|
public function getEntityTypeCode() |
|
231
|
|
|
{ |
|
232
|
|
|
|
|
233
|
|
|
// load the entity type code from the configuration |
|
234
|
22 |
|
$entityTypeCode = $this->getConfiguration()->getConfiguration()->getEntityTypeCode(); |
|
235
|
|
|
|
|
236
|
|
|
// try to map the entity type code |
|
237
|
22 |
|
if (isset($this->entityTypeCodeToAttributeSetMappings[$entityTypeCode])) { |
|
238
|
8 |
|
$entityTypeCode = $this->entityTypeCodeToAttributeSetMappings[$entityTypeCode]; |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
// return the (mapped) entity type code |
|
242
|
22 |
|
return $entityTypeCode; |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
/** |
|
246
|
|
|
* Return's the attribute set with the passed attribute set name. |
|
247
|
|
|
* |
|
248
|
|
|
* @param string $attributeSetName The name of the requested attribute set |
|
249
|
|
|
* |
|
250
|
|
|
* @return array The attribute set data |
|
251
|
|
|
* @throws \Exception Is thrown, if the attribute set or the given entity type with the passed name is not available |
|
252
|
|
|
*/ |
|
253
|
3 |
View Code Duplication |
public function getAttributeSetByAttributeSetName($attributeSetName) |
|
|
|
|
|
|
254
|
|
|
{ |
|
255
|
|
|
|
|
256
|
|
|
// query whether or not attribute sets for the actualy entity type code are available |
|
257
|
3 |
|
if (isset($this->attributeSets[$entityTypeCode = $this->getEntityTypeCode()])) { |
|
258
|
|
|
// load the attribute sets for the actualy entity type code |
|
259
|
2 |
|
$attributSets = $this->attributeSets[$entityTypeCode]; |
|
260
|
|
|
|
|
261
|
|
|
// query whether or not, the requested attribute set is available |
|
262
|
2 |
|
if (isset($attributSets[$attributeSetName])) { |
|
263
|
1 |
|
return $attributSets[$attributeSetName]; |
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
// throw an exception, if not |
|
267
|
1 |
|
throw new \Exception( |
|
268
|
1 |
|
$this->appendExceptionSuffix( |
|
269
|
1 |
|
sprintf('Found invalid attribute set name "%s"', $attributeSetName) |
|
270
|
|
|
) |
|
271
|
|
|
); |
|
272
|
|
|
} |
|
273
|
|
|
|
|
274
|
|
|
// throw an exception, if not |
|
275
|
1 |
|
throw new \Exception( |
|
276
|
1 |
|
$this->appendExceptionSuffix( |
|
277
|
1 |
|
sprintf('Found invalid entity type code "%s"', $entityTypeCode) |
|
278
|
|
|
) |
|
279
|
|
|
); |
|
280
|
|
|
} |
|
281
|
|
|
|
|
282
|
|
|
/** |
|
283
|
|
|
* Return's the attributes for the attribute set of the product that has to be created. |
|
284
|
|
|
* |
|
285
|
|
|
* @return array The attributes |
|
286
|
|
|
* @throws \Exception Is thrown, if the attribute set or the given entity type with the passed name is not available |
|
287
|
|
|
*/ |
|
288
|
5 |
View Code Duplication |
public function getAttributes() |
|
|
|
|
|
|
289
|
|
|
{ |
|
290
|
|
|
|
|
291
|
|
|
// query whether or not, the requested EAV attributes are available |
|
292
|
5 |
|
if (isset($this->attributes[$entityTypeCode = $this->getEntityTypeCode()])) { |
|
293
|
|
|
// load the attributes for the entity type code |
|
294
|
4 |
|
$attributes = $this->attributes[$entityTypeCode]; |
|
295
|
|
|
|
|
296
|
|
|
// query whether or not attributes for the actual attribute set name |
|
297
|
4 |
|
if (isset($attributes[$attributeSetName = $this->attributeSet[MemberNames::ATTRIBUTE_SET_NAME]])) { |
|
298
|
3 |
|
return $attributes[$attributeSetName]; |
|
299
|
|
|
} |
|
300
|
|
|
|
|
301
|
|
|
// throw an exception, if not |
|
302
|
1 |
|
throw new \Exception( |
|
303
|
1 |
|
$this->appendExceptionSuffix( |
|
304
|
1 |
|
sprintf('Found invalid attribute set name "%s"', $attributeSetName) |
|
305
|
|
|
) |
|
306
|
|
|
); |
|
307
|
|
|
} |
|
308
|
|
|
|
|
309
|
|
|
// throw an exception, if not |
|
310
|
1 |
|
throw new \Exception( |
|
311
|
1 |
|
$this->appendExceptionSuffix( |
|
312
|
1 |
|
sprintf('Found invalid entity type code "%s"', $entityTypeCode) |
|
313
|
|
|
) |
|
314
|
|
|
); |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
/** |
|
318
|
|
|
* Return's an array with the available user defined EAV attributes for the actual entity type. |
|
319
|
|
|
* |
|
320
|
|
|
* @return array The array with the user defined EAV attributes |
|
321
|
|
|
*/ |
|
322
|
22 |
|
public function getEavUserDefinedAttributes() |
|
323
|
|
|
{ |
|
324
|
|
|
|
|
325
|
|
|
// initialize the array with the user defined EAV attributes |
|
326
|
22 |
|
$eavUserDefinedAttributes = array(); |
|
327
|
|
|
|
|
328
|
|
|
// query whether or not user defined EAV attributes for the actualy entity type are available |
|
329
|
22 |
|
if (isset($this->userDefinedAttributes[$entityTypeCode = $this->getEntityTypeCode()])) { |
|
330
|
2 |
|
$eavUserDefinedAttributes = $this->userDefinedAttributes[$entityTypeCode]; |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
// return the array with the user defined EAV attributes |
|
334
|
22 |
|
return $eavUserDefinedAttributes; |
|
335
|
|
|
} |
|
336
|
|
|
|
|
337
|
|
|
/** |
|
338
|
|
|
* Return's the EAV attribute with the passed attribute code. |
|
339
|
|
|
* |
|
340
|
|
|
* @param string $attributeCode The attribute code |
|
341
|
|
|
* |
|
342
|
|
|
* @return array The array with the EAV attribute |
|
343
|
|
|
* @throws \Exception Is thrown if the attribute with the passed code is not available |
|
344
|
|
|
*/ |
|
345
|
2 |
|
public function getEavAttributeByAttributeCode($attributeCode) |
|
346
|
|
|
{ |
|
347
|
|
|
|
|
348
|
|
|
// load the attributes |
|
349
|
2 |
|
$attributes = $this->getAttributes(); |
|
350
|
|
|
|
|
351
|
|
|
// query whether or not the attribute exists |
|
352
|
2 |
|
if (isset($attributes[$attributeCode])) { |
|
353
|
1 |
|
return $attributes[$attributeCode]; |
|
354
|
|
|
} |
|
355
|
|
|
|
|
356
|
|
|
// throw an exception if the requested attribute is not available |
|
357
|
1 |
|
throw new \Exception( |
|
358
|
1 |
|
$this->appendExceptionSuffix( |
|
359
|
1 |
|
sprintf('Can\'t load attribute with code "%s"', $attributeCode) |
|
360
|
|
|
) |
|
361
|
|
|
); |
|
362
|
|
|
} |
|
363
|
|
|
} |
|
364
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.