1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* TechDivision\Import\Product\Media\Observers\MediaGalleryObserver |
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-product-media |
18
|
|
|
* @link http://www.techdivision.com |
19
|
|
|
*/ |
20
|
|
|
|
21
|
|
|
namespace TechDivision\Import\Product\Media\Observers; |
22
|
|
|
|
23
|
|
|
use TechDivision\Import\Utils\BackendTypeKeys; |
24
|
|
|
use TechDivision\Import\Product\Media\Utils\ColumnKeys; |
25
|
|
|
use TechDivision\Import\Product\Media\Utils\MemberNames; |
26
|
|
|
use TechDivision\Import\Product\Media\Utils\EntityTypeCodes; |
27
|
|
|
use TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface; |
28
|
|
|
use TechDivision\Import\Product\Observers\AbstractProductImportObserver; |
29
|
|
|
use TechDivision\Import\Observers\StateDetectorInterface; |
30
|
|
|
use TechDivision\Import\Observers\AttributeLoaderInterface; |
31
|
|
|
use TechDivision\Import\Observers\DynamicAttributeObserverInterface; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Observer that creates/updates the product's media gallery information. |
35
|
|
|
* |
36
|
|
|
* @author Tim Wagner <[email protected]> |
37
|
|
|
* @copyright 2016 TechDivision GmbH <[email protected]> |
38
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
39
|
|
|
* @link https://github.com/techdivision/import-product-media |
40
|
|
|
* @link http://www.techdivision.com |
41
|
|
|
*/ |
42
|
|
|
class MediaGalleryObserver extends AbstractProductImportObserver implements DynamicAttributeObserverInterface |
43
|
|
|
{ |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* The media gallery attribute code. |
47
|
|
|
* |
48
|
|
|
* @var string |
49
|
|
|
*/ |
50
|
|
|
const ATTRIBUTE_CODE = 'media_gallery'; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* The ID of the parent product the media is related to. |
54
|
|
|
* |
55
|
|
|
* @var integer |
56
|
|
|
*/ |
57
|
|
|
protected $parentId; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* The ID of the persisted media gallery entity. |
61
|
|
|
* |
62
|
|
|
* @var integer |
63
|
|
|
*/ |
64
|
|
|
protected $valueId; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* The product media processor instance. |
68
|
|
|
* |
69
|
|
|
* @var \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface |
70
|
|
|
*/ |
71
|
|
|
protected $productMediaProcessor; |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* The attribute loader instance. |
75
|
|
|
* |
76
|
|
|
* @var \TechDivision\Import\Observers\AttributeLoaderInterface |
77
|
|
|
*/ |
78
|
|
|
protected $attributeLoader; |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Initialize the "dymanmic" columns. |
82
|
|
|
* |
83
|
|
|
* @var array |
84
|
|
|
*/ |
85
|
|
|
protected $columns = array( |
86
|
|
|
EntityTypeCodes::CATALOG_PRODUCT_MEDIA_GALLERY_VALUE_TO_ENTITY => array(), |
87
|
|
|
EntityTypeCodes::CATALOG_PRODUCT_MEDIA_GALLERY => array( |
88
|
|
|
MemberNames::DISABLED => array(ColumnKeys::IMAGE_DISABLED, BackendTypeKeys::BACKEND_TYPE_INT), |
89
|
|
|
MemberNames::MEDIA_TYPE => array(ColumnKeys::MEDIA_TYPE, BackendTypeKeys::BACKEND_TYPE_VARCHAR) |
90
|
|
|
) |
91
|
|
|
); |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Array with virtual column name mappings (this is a temporary |
95
|
|
|
* solution till techdivision/import#179 as been implemented). |
96
|
|
|
* |
97
|
|
|
* @var array |
98
|
|
|
* @todo https://github.com/techdivision/import/issues/179 |
99
|
|
|
*/ |
100
|
|
|
protected $virtualMapping = array(MemberNames::DISABLED => ColumnKeys::IMAGE_DISABLED); |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Initialize the observer with the passed product media processor instance. |
104
|
|
|
* |
105
|
|
|
* @param \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface $productMediaProcessor The product media processor instance |
106
|
|
|
* @param \TechDivision\Import\Observers\AttributeLoaderInterface $attributeLoader The attribute loader instance |
107
|
|
|
* @param \TechDivision\Import\Observers\StateDetectorInterface|null $stateDetector The state detector instance to use |
108
|
|
|
*/ |
109
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
110
|
|
|
ProductMediaProcessorInterface $productMediaProcessor, |
111
|
|
|
AttributeLoaderInterface $attributeLoader = null, |
112
|
|
|
StateDetectorInterface $stateDetector = null |
113
|
|
|
) { |
114
|
|
|
|
115
|
|
|
// initialize the media processor and the dynamic attribute loader instance |
116
|
|
|
$this->productMediaProcessor = $productMediaProcessor; |
117
|
|
|
$this->attributeLoader = $attributeLoader; |
118
|
|
|
|
119
|
|
|
// pass the state detector to the parent method |
120
|
|
|
parent::__construct($stateDetector); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Return's the product media processor instance. |
125
|
|
|
* |
126
|
|
|
* @return \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface The product media processor instance |
127
|
|
|
*/ |
128
|
|
|
protected function getProductMediaProcessor() |
129
|
|
|
{ |
130
|
|
|
return $this->productMediaProcessor; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Query whether or not a value for the column with the passed name exists. |
135
|
|
|
* |
136
|
|
|
* @param string $name The column name to query for a valid value |
137
|
|
|
* |
138
|
|
|
* @return boolean TRUE if the value is set, else FALSE |
139
|
|
|
* @todo https://github.com/techdivision/import/issues/179 |
140
|
|
|
*/ |
141
|
|
|
public function hasValue($name) |
142
|
|
|
{ |
143
|
|
|
return parent::hasValue(isset($this->virtualMapping[$name]) ? $this->virtualMapping[$name] : $name); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Process the observer's business logic. |
148
|
|
|
* |
149
|
|
|
* @return array The processed row |
150
|
|
|
*/ |
151
|
|
|
protected function process() |
152
|
|
|
{ |
153
|
|
|
|
154
|
|
|
// try to load the product SKU and map it the entity ID and |
155
|
|
|
$this->parentId = $this->getValue(ColumnKeys::IMAGE_PARENT_SKU, null, array($this, 'mapParentSku')); |
156
|
|
|
|
157
|
|
|
// prepare the actual store view code |
158
|
|
|
$this->prepareStoreViewCode($this->getRow()); |
|
|
|
|
159
|
|
|
|
160
|
|
|
// initialize and persist the product media gallery |
161
|
|
|
$attr = $this->prepareDynamicMediaGalleryAttributes(EntityTypeCodes::CATALOG_PRODUCT_MEDIA_GALLERY, $this->prepareProductMediaGalleryAttributes()); |
162
|
|
|
if ($this->hasChanges($productMediaGallery = $this->initializeProductMediaGallery($attr))) { |
163
|
|
|
// persist the media gallery data and temporarily persist value ID |
164
|
|
|
$this->setParentValueId($this->valueId = $this->persistProductMediaGallery($productMediaGallery)); |
|
|
|
|
165
|
|
|
// persist the product media gallery to entity data |
166
|
|
|
$attr = $this->prepareDynamicMediaGalleryAttributes(EntityTypeCodes::CATALOG_PRODUCT_MEDIA_GALLERY_VALUE_TO_ENTITY, $this->prepareProductMediaGalleryValueToEntityAttributes()); |
167
|
|
|
if ($productMediaGalleryValueToEntity = $this->initializeProductMediaGalleryValueToEntity($attr)) { |
168
|
|
|
$this->persistProductMediaGalleryValueToEntity($productMediaGalleryValueToEntity); |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
// temporarily persist parent ID |
173
|
|
|
$this->setParentId($this->parentId); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Appends the dynamic attributes to the static ones and returns them. |
178
|
|
|
* |
179
|
|
|
* @param string $entityTypeCode The entity type code load to append the dynamic attributes for |
180
|
|
|
* @param array $staticAttributes The array with the static attributes to append the dynamic to |
181
|
|
|
* |
182
|
|
|
* @return array The array with all available attributes |
183
|
|
|
*/ |
184
|
|
|
protected function prepareDynamicMediaGalleryAttributes(string $entityTypeCode, array $staticAttributes) : array |
185
|
|
|
{ |
186
|
|
|
return array_merge( |
187
|
|
|
$staticAttributes, |
188
|
|
|
$this->attributeLoader ? $this->attributeLoader->load($this, $this->columns[$entityTypeCode]) : array() |
189
|
|
|
); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Prepare the product media gallery that has to be persisted. |
194
|
|
|
* |
195
|
|
|
* @return array The prepared product media gallery attributes |
196
|
|
|
*/ |
197
|
|
|
protected function prepareProductMediaGalleryAttributes() |
198
|
|
|
{ |
199
|
|
|
|
200
|
|
|
// load the attribute ID of the media gallery EAV attribute |
201
|
|
|
$mediaGalleryAttribute = $this->getEavAttributeByAttributeCode(MediaGalleryObserver::ATTRIBUTE_CODE); |
202
|
|
|
$attributeId = $mediaGalleryAttribute[MemberNames::ATTRIBUTE_ID]; |
203
|
|
|
|
204
|
|
|
// initialize the gallery data |
205
|
|
|
$image = $this->getValue(ColumnKeys::IMAGE_PATH_NEW); |
206
|
|
|
|
207
|
|
|
// initialize and return the entity |
208
|
|
|
return $this->initializeEntity( |
209
|
|
|
$this->loadRawEntity( |
210
|
|
|
EntityTypeCodes::CATALOG_PRODUCT_MEDIA_GALLERY, |
211
|
|
|
array( |
212
|
|
|
MemberNames::ATTRIBUTE_ID => $attributeId, |
213
|
|
|
MemberNames::VALUE => $image |
214
|
|
|
) |
215
|
|
|
) |
216
|
|
|
); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Prepare the product media gallery value to entity that has to be persisted. |
221
|
|
|
* |
222
|
|
|
* @return array The prepared product media gallery value to entity attributes |
223
|
|
|
*/ |
224
|
|
|
protected function prepareProductMediaGalleryValueToEntityAttributes() |
225
|
|
|
{ |
226
|
|
|
|
227
|
|
|
// initialize and return the entity |
228
|
|
|
return $this->initializeEntity( |
229
|
|
|
$this->loadRawEntity( |
230
|
|
|
EntityTypeCodes::CATALOG_PRODUCT_MEDIA_GALLERY_VALUE_TO_ENTITY, |
231
|
|
|
array( |
232
|
|
|
MemberNames::VALUE_ID => $this->valueId, |
233
|
|
|
MemberNames::ENTITY_ID => $this->parentId |
234
|
|
|
) |
235
|
|
|
) |
236
|
|
|
); |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Load's and return's a raw entity without primary key but the mandatory members only and nulled values. |
241
|
|
|
* |
242
|
|
|
* @param string $entityTypeCode The entity type code to return the raw entity for |
243
|
|
|
* @param array $data An array with data that will be used to initialize the raw entity with |
244
|
|
|
* |
245
|
|
|
* @return array The initialized entity |
246
|
|
|
*/ |
247
|
|
|
protected function loadRawEntity($entityTypeCode, array $data = array()) |
248
|
|
|
{ |
249
|
|
|
return $this->getProductMediaProcessor()->loadRawEntity($entityTypeCode, $data); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Initialize the product media gallery with the passed attributes and returns an instance. |
254
|
|
|
* |
255
|
|
|
* @param array $attr The product media gallery attributes |
256
|
|
|
* |
257
|
|
|
* @return array The initialized product media gallery |
258
|
|
|
*/ |
259
|
|
|
protected function initializeProductMediaGallery(array $attr) |
260
|
|
|
{ |
261
|
|
|
return $attr; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Initialize the product media gallery value to entity with the passed attributes and returns an instance. |
266
|
|
|
* |
267
|
|
|
* @param array $attr The product media gallery value to entity attributes |
268
|
|
|
* |
269
|
|
|
* @return array|null The initialized product media gallery value to entity, or NULL if the product media gallery value to entity already exists |
270
|
|
|
*/ |
271
|
|
|
protected function initializeProductMediaGalleryValueToEntity(array $attr) |
272
|
|
|
{ |
273
|
|
|
return $attr; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* Map's the passed SKU of the parent product to it's PK. |
278
|
|
|
* |
279
|
|
|
* @param string $parentSku The SKU of the parent product |
280
|
|
|
* |
281
|
|
|
* @return integer The primary key used to create relations |
282
|
|
|
*/ |
283
|
|
|
protected function mapParentSku($parentSku) |
284
|
|
|
{ |
285
|
|
|
return $this->mapSkuToEntityId($parentSku); |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* Set's the value ID of the created media gallery entry. |
290
|
|
|
* |
291
|
|
|
* @param integer $parentValueId The ID of the created media gallery entry |
292
|
|
|
* |
293
|
|
|
* @return void |
294
|
|
|
*/ |
295
|
|
|
protected function setParentValueId($parentValueId) |
296
|
|
|
{ |
297
|
|
|
$this->getSubject()->setParentValueId($parentValueId); |
|
|
|
|
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* Return the entity ID for the passed SKU. |
302
|
|
|
* |
303
|
|
|
* @param string $sku The SKU to return the entity ID for |
304
|
|
|
* |
305
|
|
|
* @return integer The mapped entity ID |
306
|
|
|
* @throws \Exception Is thrown if the SKU is not mapped yet |
307
|
|
|
*/ |
308
|
|
|
protected function mapSkuToEntityId($sku) |
309
|
|
|
{ |
310
|
|
|
return $this->getSubject()->mapSkuToEntityId($sku); |
|
|
|
|
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* Set's the ID of the parent product to relate the variant with. |
315
|
|
|
* |
316
|
|
|
* @param integer $parentId The ID of the parent product |
317
|
|
|
* |
318
|
|
|
* @return void |
319
|
|
|
*/ |
320
|
|
|
protected function setParentId($parentId) |
321
|
|
|
{ |
322
|
|
|
$this->getSubject()->setParentId($parentId); |
|
|
|
|
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Return's the ID of the parent product to relate the variant with. |
327
|
|
|
* |
328
|
|
|
* @return integer The ID of the parent product |
329
|
|
|
*/ |
330
|
|
|
protected function getParentId() |
331
|
|
|
{ |
332
|
|
|
return $this->getSubject()->getParentId(); |
|
|
|
|
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Query whether or not this is the parent ID. |
337
|
|
|
* |
338
|
|
|
* @param integer $parentId The PK of the parent image |
339
|
|
|
* |
340
|
|
|
* @return boolean TRUE if the PK euqals, else FALSE |
341
|
|
|
*/ |
342
|
|
|
protected function isParentId($parentId) |
343
|
|
|
{ |
344
|
|
|
return $this->getParentId() === $parentId; |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* Query whether or not this is the parent store view code. |
349
|
|
|
* |
350
|
|
|
* @param string $storeViewCode The actual store view code |
351
|
|
|
* |
352
|
|
|
* @return boolean TRUE if the store view code equals, else FALSE |
353
|
|
|
*/ |
354
|
|
|
protected function isParentStoreViewCode($storeViewCode) |
355
|
|
|
{ |
356
|
|
|
return $this->getStoreViewCode() === $storeViewCode; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* Return's the default store view code. |
361
|
|
|
* |
362
|
|
|
* @return array The default store view code |
363
|
|
|
*/ |
364
|
|
|
protected function getDefaultStoreViewCode() |
365
|
|
|
{ |
366
|
|
|
return $this->getSubject()->getDefaultStoreViewCode(); |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* Reset the position counter to 1. |
371
|
|
|
* |
372
|
|
|
* @return void |
373
|
|
|
* @deprecated Since 23.0.0 |
374
|
|
|
*/ |
375
|
|
|
protected function resetPositionCounter() |
376
|
|
|
{ |
377
|
|
|
$this->getSubject()->resetPositionCounter(); |
|
|
|
|
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Return's the EAV attribute with the passed attribute code. |
382
|
|
|
* |
383
|
|
|
* @param string $attributeCode The attribute code |
384
|
|
|
* |
385
|
|
|
* @return array The array with the EAV attribute |
386
|
|
|
* @throws \Exception Is thrown if the attribute with the passed code is not available |
387
|
|
|
*/ |
388
|
|
|
protected function getEavAttributeByAttributeCode($attributeCode) |
389
|
|
|
{ |
390
|
|
|
return $this->getSubject()->getEavAttributeByAttributeCode($attributeCode); |
|
|
|
|
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
/** |
394
|
|
|
* Persist's the passed product media gallery data and return's the ID. |
395
|
|
|
* |
396
|
|
|
* @param array $productMediaGallery The product media gallery data to persist |
397
|
|
|
* |
398
|
|
|
* @return string The ID of the persisted entity |
399
|
|
|
*/ |
400
|
|
|
protected function persistProductMediaGallery($productMediaGallery) |
401
|
|
|
{ |
402
|
|
|
return $this->getProductMediaProcessor()->persistProductMediaGallery($productMediaGallery); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* Persist's the passed product media gallery value to entity data. |
407
|
|
|
* |
408
|
|
|
* @param array $productMediaGalleryValueToEntity The product media gallery value to entity data to persist |
409
|
|
|
* |
410
|
|
|
* @return void |
411
|
|
|
*/ |
412
|
|
|
protected function persistProductMediaGalleryValueToEntity($productMediaGalleryValueToEntity) |
413
|
|
|
{ |
414
|
|
|
$this->getProductMediaProcessor()->persistProductMediaGalleryValueToEntity($productMediaGalleryValueToEntity); |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
|
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.