@@ -108,40 +108,161 @@ public function __construct(
108
108
public function saveMediaGallery (array $ mediaGalleryData )
109
109
{
110
110
$ this ->initMediaGalleryResources ();
111
- $ mediaGalleryDataGlobal = array_replace_recursive (...$ mediaGalleryData );
112
- $ imageNames = [];
113
- $ multiInsertData = [];
114
- $ valueToProductId = [];
115
- foreach ($ mediaGalleryDataGlobal as $ productSku => $ mediaGalleryRows ) {
116
- $ productId = $ this ->skuProcessor ->getNewSku ($ productSku )[$ this ->getProductEntityLinkField ()];
117
- $ insertedGalleryImgs = [];
118
- foreach ($ mediaGalleryRows as $ insertValue ) {
119
- if (!in_array ($ insertValue ['value ' ], $ insertedGalleryImgs )) {
120
- $ valueArr = [
121
- 'attribute_id ' => $ insertValue ['attribute_id ' ],
122
- 'value ' => $ insertValue ['value ' ],
111
+ $ mediaGalleryValues = [];
112
+ $ mediaGalleryValueData = [];
113
+ $ productMediaGalleryValueData = [];
114
+ $ mediaGalleryValueToEntityData = [];
115
+ $ mediaGalleryValueToStoreData = [];
116
+ $ productLinkIdField = $ this ->getProductEntityLinkField ();
117
+ foreach ($ mediaGalleryData as $ storeId => $ storeMediaGalleryData ) {
118
+ foreach ($ storeMediaGalleryData as $ sku => $ productMediaGalleryData ) {
119
+ $ productId = $ this ->skuProcessor ->getNewSku ($ sku )[$ productLinkIdField ];
120
+ $ productMediaGalleryValueData [$ productId ] = $ productMediaGalleryValueData [$ productId ] ?? [];
121
+ foreach ($ productMediaGalleryData as $ data ) {
122
+ if (!in_array ($ data ['value ' ], $ productMediaGalleryValueData [$ productId ])) {
123
+ $ productMediaGalleryValueData [$ productId ][] = $ data ['value ' ];
124
+ $ mediaGalleryValueData [] = [
125
+ 'attribute_id ' => $ data ['attribute_id ' ],
126
+ 'value ' => $ data ['value ' ],
127
+ ];
128
+ $ mediaGalleryValueToEntityData [] = [
129
+ 'value ' => $ data ['value ' ],
130
+ $ productLinkIdField => $ productId ,
131
+ ];
132
+ }
133
+ $ mediaGalleryValues [] = $ data ['value ' ];
134
+ $ mediaGalleryValueToStoreData [] = [
135
+ 'value ' => $ data ['value ' ],
136
+ 'store_id ' => $ storeId ,
137
+ $ productLinkIdField => $ productId ,
138
+ 'label ' => $ data ['label ' ],
139
+ 'position ' => $ data ['position ' ],
140
+ 'disabled ' => $ data ['disabled ' ],
123
141
];
124
- $ valueToProductId [$ insertValue ['value ' ]][] = $ productId ;
125
- $ imageNames [] = $ insertValue ['value ' ];
126
- $ multiInsertData [] = $ valueArr ;
127
- $ insertedGalleryImgs [] = $ insertValue ['value ' ];
128
142
}
129
143
}
130
144
}
131
- $ oldMediaValues = $ this ->connection ->fetchAssoc (
132
- $ this ->connection ->select ()->from ($ this ->mediaGalleryTableName , ['value_id ' , 'value ' ])
133
- ->where ('value IN (?) ' , $ imageNames )
134
- );
135
- $ this ->connection ->insertOnDuplicate ($ this ->mediaGalleryTableName , $ multiInsertData );
136
- $ newMediaSelect = $ this ->connection ->select ()->from ($ this ->mediaGalleryTableName , ['value_id ' , 'value ' ])
137
- ->where ('value IN (?) ' , $ imageNames );
138
- if (array_keys ($ oldMediaValues )) {
139
- $ newMediaSelect ->where ('value_id NOT IN (?) ' , array_keys ($ oldMediaValues ));
145
+ try {
146
+ $ mediaValueIdValueMap = [];
147
+ $ oldMediaValues = $ this ->connection ->fetchCol (
148
+ $ this ->connection ->select ()
149
+ ->from ($ this ->mediaGalleryTableName , ['value_id ' ])
150
+ ->where ('value IN (?) ' , $ mediaGalleryValues )
151
+ );
152
+ $ this ->connection ->insertOnDuplicate (
153
+ $ this ->mediaGalleryTableName ,
154
+ $ mediaGalleryValueData
155
+ );
156
+ $ newMediaSelect = $ this ->connection ->select ()
157
+ ->from ($ this ->mediaGalleryTableName , ['value_id ' , 'value ' ])
158
+ ->where ('value IN (?) ' , $ mediaGalleryValues );
159
+ if ($ oldMediaValues ) {
160
+ $ newMediaSelect ->where ('value_id NOT IN (?) ' , $ oldMediaValues );
161
+ }
162
+ $ mediaValueIdValueMap = $ this ->connection ->fetchPairs ($ newMediaSelect );
163
+ $ productIdMediaValueIdMap = $ this ->getProductIdMediaValueIdMap (
164
+ $ productMediaGalleryValueData ,
165
+ $ mediaValueIdValueMap
166
+ );
167
+ $ mediaGalleryValueToEntityData = $ this ->prepareMediaGalleryValueToEntityData (
168
+ $ mediaGalleryValueToEntityData ,
169
+ $ productIdMediaValueIdMap
170
+ );
171
+ $ this ->connection ->insertOnDuplicate (
172
+ $ this ->mediaGalleryEntityToValueTableName ,
173
+ $ mediaGalleryValueToEntityData ,
174
+ ['value_id ' ]
175
+ );
176
+ $ mediaGalleryValueToStoreData = $ this ->prepareMediaGalleryValueData (
177
+ $ mediaGalleryValueToStoreData ,
178
+ $ productIdMediaValueIdMap
179
+ );
180
+ $ this ->connection ->insertOnDuplicate (
181
+ $ this ->mediaGalleryValueTableName ,
182
+ $ mediaGalleryValueToStoreData ,
183
+ ['value_id ' , 'store_id ' , $ productLinkIdField , 'label ' , 'position ' , 'disabled ' ]
184
+ );
185
+ } catch (\Throwable $ exception ) {
186
+ if ($ mediaValueIdValueMap ) {
187
+ $ this ->connection ->delete (
188
+ $ this ->mediaGalleryTableName ,
189
+ $ this ->connection ->quoteInto ('value_id IN (?) ' , array_keys ($ mediaValueIdValueMap ))
190
+ );
191
+ }
192
+ throw $ exception ;
140
193
}
141
- $ newMediaValues = $ this ->connection ->fetchAssoc ($ newMediaSelect );
142
- foreach ($ mediaGalleryData as $ storeId => $ storeMediaGalleryData ) {
143
- $ this ->processMediaPerStore ((int )$ storeId , $ storeMediaGalleryData , $ newMediaValues , $ valueToProductId );
194
+ }
195
+
196
+ /**
197
+ * Get media values IDs per products IDs
198
+ *
199
+ * @param array $productMediaGalleryValueData
200
+ * @param array $mediaValueIdValueMap
201
+ * @return array
202
+ */
203
+ private function getProductIdMediaValueIdMap (
204
+ array $ productMediaGalleryValueData ,
205
+ array $ mediaValueIdValueMap
206
+ ): array {
207
+ $ productIdMediaValueIdMap = [];
208
+ foreach ($ productMediaGalleryValueData as $ productId => $ productMediaGalleryValues ) {
209
+ foreach ($ productMediaGalleryValues as $ productMediaGalleryValue ) {
210
+ foreach ($ mediaValueIdValueMap as $ valueId => $ value ) {
211
+ if ($ productMediaGalleryValue === $ value ) {
212
+ $ productIdMediaValueIdMap [$ productId ][$ value ] = $ valueId ;
213
+ unset($ mediaValueIdValueMap [$ valueId ]);
214
+ break ;
215
+ }
216
+ }
217
+ }
218
+ }
219
+ return $ productIdMediaValueIdMap ;
220
+ }
221
+
222
+ /**
223
+ * Prepare media entity gallery value to entity data for insert
224
+ *
225
+ * @param array $mediaGalleryValueToEntityData
226
+ * @param array $productIdMediaValueIdMap
227
+ * @return array
228
+ */
229
+ private function prepareMediaGalleryValueToEntityData (
230
+ array $ mediaGalleryValueToEntityData ,
231
+ array $ productIdMediaValueIdMap
232
+ ): array {
233
+ $ productLinkIdField = $ this ->getProductEntityLinkField ();
234
+ foreach ($ mediaGalleryValueToEntityData as $ index => $ data ) {
235
+ $ productId = $ data [$ productLinkIdField ];
236
+ $ value = $ data ['value ' ];
237
+ $ mediaGalleryValueToEntityData [$ index ]['value_id ' ] = $ productIdMediaValueIdMap [$ productId ][$ value ];
238
+ unset($ mediaGalleryValueToEntityData [$ index ]['value ' ]);
239
+ }
240
+ return $ mediaGalleryValueToEntityData ;
241
+ }
242
+
243
+ /**
244
+ * Prepare media entity gallery value data for insert
245
+ *
246
+ * @param array $mediaGalleryValueData
247
+ * @param array $productIdMediaValueIdMap
248
+ * @return array
249
+ */
250
+ private function prepareMediaGalleryValueData (
251
+ array $ mediaGalleryValueData ,
252
+ array $ productIdMediaValueIdMap
253
+ ): array {
254
+ $ productLinkIdField = $ this ->getProductEntityLinkField ();
255
+ $ lastPositions = $ this ->getLastMediaPositionPerProduct (array_keys ($ productIdMediaValueIdMap ));
256
+ foreach ($ mediaGalleryValueData as $ index => $ data ) {
257
+ $ productId = $ data [$ productLinkIdField ];
258
+ $ value = $ data ['value ' ];
259
+ $ position = $ data ['position ' ];
260
+ $ storeId = $ data ['store_id ' ];
261
+ $ mediaGalleryValueData [$ index ]['value_id ' ] = $ productIdMediaValueIdMap [$ productId ][$ value ];
262
+ $ mediaGalleryValueData [$ index ]['position ' ] = $ position + ($ lastPositions [$ storeId ][$ productId ] ?? 0 );
263
+ unset($ mediaGalleryValueData [$ index ]['value ' ]);
144
264
}
265
+ return $ mediaGalleryValueData ;
145
266
}
146
267
147
268
/**
@@ -289,13 +410,12 @@ private function initMediaGalleryResources()
289
410
}
290
411
291
412
/**
292
- * Get the last media position for each product from the given list
413
+ * Get the last media position for each product per store from the given list
293
414
*
294
- * @param int $storeId
295
415
* @param array $productIds
296
416
* @return array
297
417
*/
298
- private function getLastMediaPositionPerProduct (int $ storeId , array $ productIds ): array
418
+ private function getLastMediaPositionPerProduct (array $ productIds ): array
299
419
{
300
420
$ result = [];
301
421
if ($ productIds ) {
@@ -305,95 +425,25 @@ private function getLastMediaPositionPerProduct(int $storeId, array $productIds)
305
425
$ positions = $ this ->connection ->fetchAll (
306
426
$ this ->connection
307
427
->select ()
308
- ->from ($ this ->mediaGalleryValueTableName , [$ productKeyName , 'position ' ])
428
+ ->from ($ this ->mediaGalleryValueTableName , [$ productKeyName , 'store_id ' , ' position ' ])
309
429
->where ("$ productKeyName IN (?) " , $ productIds )
310
- ->where ('value_id is not null ' )
311
- ->where ('store_id = ? ' , $ storeId )
312
430
);
313
- // Make sure the result contains all product ids even if the product has no media files
314
- $ result = array_fill_keys ($ productIds , 0 );
315
431
// Find the largest position for each product
316
432
foreach ($ positions as $ record ) {
317
433
$ productId = $ record [$ productKeyName ];
318
- $ result [$ productId ] = $ result [$ productId ] < $ record ['position ' ]
434
+ $ storeId = $ record ['store_id ' ];
435
+ if (!isset ($ result [$ storeId ][$ productId ])) {
436
+ $ result [$ storeId ][$ productId ] = 0 ;
437
+ }
438
+ $ result [$ storeId ][$ productId ] = $ result [$ storeId ][$ productId ] < $ record ['position ' ]
319
439
? $ record ['position ' ]
320
- : $ result [$ productId ];
440
+ : $ result [$ storeId ][ $ productId ];
321
441
}
322
442
}
323
443
324
444
return $ result ;
325
445
}
326
446
327
- /**
328
- * Save media gallery data per store.
329
- *
330
- * @param int $storeId
331
- * @param array $mediaGalleryData
332
- * @param array $newMediaValues
333
- * @param array $valueToProductId
334
- * @return void
335
- */
336
- private function processMediaPerStore (
337
- int $ storeId ,
338
- array $ mediaGalleryData ,
339
- array $ newMediaValues ,
340
- array $ valueToProductId
341
- ) {
342
- $ multiInsertData = [];
343
- $ dataForSkinnyTable = [];
344
- $ lastMediaPositionPerProduct = $ this ->getLastMediaPositionPerProduct (
345
- $ storeId ,
346
- array_unique (array_merge (...array_values ($ valueToProductId )))
347
- );
348
-
349
- foreach ($ mediaGalleryData as $ mediaGalleryRows ) {
350
- foreach ($ mediaGalleryRows as $ insertValue ) {
351
- foreach ($ newMediaValues as $ valueId => $ values ) {
352
- if ($ values ['value ' ] == $ insertValue ['value ' ]) {
353
- $ insertValue ['value_id ' ] = $ valueId ;
354
- $ insertValue [$ this ->getProductEntityLinkField ()]
355
- = array_shift ($ valueToProductId [$ values ['value ' ]]);
356
- unset($ newMediaValues [$ valueId ]);
357
- break ;
358
- }
359
- }
360
- if (isset ($ insertValue ['value_id ' ])) {
361
- $ productId = $ insertValue [$ this ->getProductEntityLinkField ()];
362
- $ valueArr = [
363
- 'value_id ' => $ insertValue ['value_id ' ],
364
- 'store_id ' => $ storeId ,
365
- $ this ->getProductEntityLinkField () => $ productId ,
366
- 'label ' => $ insertValue ['label ' ],
367
- 'position ' => $ lastMediaPositionPerProduct [$ productId ] + $ insertValue ['position ' ],
368
- 'disabled ' => $ insertValue ['disabled ' ],
369
- ];
370
- $ multiInsertData [] = $ valueArr ;
371
- $ dataForSkinnyTable [] = [
372
- 'value_id ' => $ insertValue ['value_id ' ],
373
- $ this ->getProductEntityLinkField () => $ insertValue [$ this ->getProductEntityLinkField ()],
374
- ];
375
- }
376
- }
377
- }
378
- try {
379
- $ this ->connection ->insertOnDuplicate (
380
- $ this ->mediaGalleryValueTableName ,
381
- $ multiInsertData ,
382
- ['value_id ' , 'store_id ' , $ this ->getProductEntityLinkField (), 'label ' , 'position ' , 'disabled ' ]
383
- );
384
- $ this ->connection ->insertOnDuplicate (
385
- $ this ->mediaGalleryEntityToValueTableName ,
386
- $ dataForSkinnyTable ,
387
- ['value_id ' ]
388
- );
389
- } catch (\Exception $ e ) {
390
- $ this ->connection ->delete (
391
- $ this ->mediaGalleryTableName ,
392
- $ this ->connection ->quoteInto ('value_id IN (?) ' , $ newMediaValues )
393
- );
394
- }
395
- }
396
-
397
447
/**
398
448
* Get product entity link field.
399
449
*
0 commit comments