Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
MediaGalleryProcessor.php
Go to the documentation of this file.
1 <?php
8 
11 use Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceModelFactory;
16 
22 {
26  private $skuProcessor;
27 
31  private $metadataPool;
32 
38  private $connection;
39 
43  private $resourceFactory;
44 
48  private $resourceModel;
49 
53  private $errorAggregator;
54 
58  private $productEntityLinkField;
59 
63  private $mediaGalleryTableName;
64 
68  private $mediaGalleryValueTableName;
69 
73  private $mediaGalleryEntityToValueTableName;
74 
78  private $productEntityTableName;
79 
89  public function __construct(
90  SkuProcessor $skuProcessor,
91  MetadataPool $metadataPool,
93  ResourceModelFactory $resourceModelFactory,
94  ProcessingErrorAggregatorInterface $errorAggregator
95  ) {
96  $this->skuProcessor = $skuProcessor;
97  $this->metadataPool = $metadataPool;
98  $this->connection = $resourceConnection->getConnection();
99  $this->resourceFactory = $resourceModelFactory;
100  $this->errorAggregator = $errorAggregator;
101  }
102 
109  public function saveMediaGallery(array $mediaGalleryData)
110  {
111  $this->initMediaGalleryResources();
112  $mediaGalleryDataGlobal = array_replace_recursive(...$mediaGalleryData);
113  $imageNames = [];
114  $multiInsertData = [];
115  $valueToProductId = [];
116  foreach ($mediaGalleryDataGlobal as $productSku => $mediaGalleryRows) {
117  $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()];
118  $insertedGalleryImgs = [];
119  foreach ($mediaGalleryRows as $insertValue) {
120  if (!in_array($insertValue['value'], $insertedGalleryImgs)) {
121  $valueArr = [
122  'attribute_id' => $insertValue['attribute_id'],
123  'value' => $insertValue['value'],
124  ];
125  $valueToProductId[$insertValue['value']][] = $productId;
126  $imageNames[] = $insertValue['value'];
127  $multiInsertData[] = $valueArr;
128  $insertedGalleryImgs[] = $insertValue['value'];
129  }
130  }
131  }
132  $oldMediaValues = $this->connection->fetchAssoc(
133  $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value'])
134  ->where('value IN (?)', $imageNames)
135  );
136  $this->connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData);
137  $newMediaSelect = $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value'])
138  ->where('value IN (?)', $imageNames);
139  if (array_keys($oldMediaValues)) {
140  $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues));
141  }
142  $newMediaValues = $this->connection->fetchAssoc($newMediaSelect);
143  foreach ($mediaGalleryData as $storeId => $storeMediaGalleryData) {
144  $this->processMediaPerStore((int)$storeId, $storeMediaGalleryData, $newMediaValues, $valueToProductId);
145  }
146  }
147 
154  public function updateMediaGalleryLabels(array $labels)
155  {
156  $this->updateMediaGalleryField($labels, 'label');
157  }
158 
165  public function updateMediaGalleryVisibility(array $images)
166  {
167  $this->updateMediaGalleryField($images, 'disabled');
168  }
169 
177  private function updateMediaGalleryField(array $data, $field)
178  {
179  $insertData = [];
180  foreach ($data as $datum) {
181  $imageData = $datum['imageData'];
182 
183  if ($imageData[$field] === null) {
184  $insertData[] = [
185  $field => $datum[$field],
186  $this->getProductEntityLinkField() => $imageData[$this->getProductEntityLinkField()],
187  'value_id' => $imageData['value_id'],
188  'store_id' => Store::DEFAULT_STORE_ID,
189  ];
190  } else {
191  $this->connection->update(
192  $this->mediaGalleryValueTableName,
193  [
194  $field => $datum[$field],
195  ],
196  [
197  $this->getProductEntityLinkField() . ' = ?' => $imageData[$this->getProductEntityLinkField()],
198  'value_id = ?' => $imageData['value_id'],
199  'store_id = ?' => Store::DEFAULT_STORE_ID,
200  ]
201  );
202  }
203  }
204 
205  if (!empty($insertData)) {
206  $this->connection->insertMultiple(
207  $this->mediaGalleryValueTableName,
208  $insertData
209  );
210  }
211  }
212 
219  public function getExistingImages(array $bunch)
220  {
221  $result = [];
222  if ($this->errorAggregator->hasToBeTerminated()) {
223  return $result;
224  }
225  $this->initMediaGalleryResources();
226  $productSKUs = array_map(
227  'strval',
228  array_column($bunch, Product::COL_SKU)
229  );
230  $select = $this->connection->select()->from(
231  ['mg' => $this->mediaGalleryTableName],
232  ['value' => 'mg.value']
233  )->joinInner(
234  ['mgvte' => $this->mediaGalleryEntityToValueTableName],
235  '(mg.value_id = mgvte.value_id)',
236  [
237  $this->getProductEntityLinkField() => 'mgvte.' . $this->getProductEntityLinkField(),
238  'value_id' => 'mgvte.value_id',
239  ]
240  )->joinLeft(
241  ['mgv' => $this->mediaGalleryValueTableName],
242  sprintf(
243  '(mg.value_id = mgv.value_id AND mgv.%s = mgvte.%s AND mgv.store_id = %d)',
244  $this->getProductEntityLinkField(),
245  $this->getProductEntityLinkField(),
247  ),
248  [
249  'label' => 'mgv.label',
250  'disabled' => 'mgv.disabled',
251  ]
252  )->joinInner(
253  ['pe' => $this->productEntityTableName],
254  "(mgvte.{$this->getProductEntityLinkField()} = pe.{$this->getProductEntityLinkField()})",
255  ['sku' => 'pe.sku']
256  )->where(
257  'pe.sku IN (?)',
258  $productSKUs
259  );
260 
261  foreach ($this->connection->fetchAll($select) as $image) {
262  $result[$image['sku']][$image['value']] = $image;
263  }
264 
265  return $result;
266  }
267 
273  private function initMediaGalleryResources()
274  {
275  if (null == $this->mediaGalleryTableName) {
276  $this->productEntityTableName = $this->getResource()->getTable('catalog_product_entity');
277  $this->mediaGalleryTableName = $this->getResource()->getTable('catalog_product_entity_media_gallery');
278  $this->mediaGalleryValueTableName = $this->getResource()->getTable(
279  'catalog_product_entity_media_gallery_value'
280  );
281  $this->mediaGalleryEntityToValueTableName = $this->getResource()->getTable(
282  'catalog_product_entity_media_gallery_value_to_entity'
283  );
284  }
285  }
286 
296  private function processMediaPerStore(
297  int $storeId,
298  array $mediaGalleryData,
299  array $newMediaValues,
300  array $valueToProductId
301  ) {
302  $multiInsertData = [];
303  $dataForSkinnyTable = [];
304  foreach ($mediaGalleryData as $mediaGalleryRows) {
305  foreach ($mediaGalleryRows as $insertValue) {
306  foreach ($newMediaValues as $value_id => $values) {
307  if ($values['value'] == $insertValue['value']) {
308  $insertValue['value_id'] = $value_id;
309  $insertValue[$this->getProductEntityLinkField()]
310  = array_shift($valueToProductId[$values['value']]);
311  unset($newMediaValues[$value_id]);
312  break;
313  }
314  }
315  if (isset($insertValue['value_id'])) {
316  $valueArr = [
317  'value_id' => $insertValue['value_id'],
318  'store_id' => $storeId,
319  $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()],
320  'label' => $insertValue['label'],
321  'position' => $insertValue['position'],
322  'disabled' => $insertValue['disabled'],
323  ];
324  $multiInsertData[] = $valueArr;
325  $dataForSkinnyTable[] = [
326  'value_id' => $insertValue['value_id'],
327  $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()],
328  ];
329  }
330  }
331  }
332  try {
333  $this->connection->insertOnDuplicate(
334  $this->mediaGalleryValueTableName,
335  $multiInsertData,
336  ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled']
337  );
338  $this->connection->insertOnDuplicate(
339  $this->mediaGalleryEntityToValueTableName,
340  $dataForSkinnyTable,
341  ['value_id']
342  );
343  } catch (\Exception $e) {
344  $this->connection->delete(
345  $this->mediaGalleryTableName,
346  $this->connection->quoteInto('value_id IN (?)', $newMediaValues)
347  );
348  }
349  }
350 
356  private function getProductEntityLinkField()
357  {
358  if (!$this->productEntityLinkField) {
359  $this->productEntityLinkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
360  }
361 
362  return $this->productEntityLinkField;
363  }
364 
370  private function getResource()
371  {
372  if (!$this->resourceModel) {
373  $this->resourceModel = $this->resourceFactory->create();
374  }
375 
376  return $this->resourceModel;
377  }
378 }
$values
Definition: options.phtml:88