Skip to content

Commit f7d4822

Browse files
🔃 [EngCom] Public Pull Requests - 2.3-develop
Accepted Public Pull Requests: - #21633: [Forwardport] Resolve incorrect scope code selection when the requested scopeCode is null (by @mage2pratik) - #21486: Fix for issue #21477 sets CURRENT_TIMESTAMP on updated_at fields (by @dverkade) - #21549: Fixed curl adapter to properly set http version based on $http_ver argument (by @davidalger) - #20842: REST products update category_ids cannot be removed (by @ygyryn) - #19653: Adding product from wishlist not adding to cart showing warning message. (by @khodu) Fixed GitHub Issues: - #16939: Incorrect configuration scope is occasionally returned when attempting to resolve a null scope id (reported by @matthew-muscat) has been fixed in #21633 by @mage2pratik in 2.3-develop branch Related commits: 1. bc8f909 2. ca16809 3. 9e5fdbb 4. e2ce243 - #21477: Magento 2.3 quote_item table has incorrect default value in declarative schema (reported by @julianvdrielen) has been fixed in #21486 by @dverkade in 2.3-develop branch Related commits: 1. ce441c6 - #20481: REST products update category_ids cannot be removed (reported by @siliconalchemy) has been fixed in #20842 by @ygyryn in 2.3-develop branch Related commits: 1. 9dc3a19 2. b602067 3. d1b7097 4. 8149479 5. bd46d50 6. 96b6feb - #9155: Adding product from wishlist not adding to cart showing warning message. (reported by @KishorkumarKar) has been fixed in #19653 by @khodu in 2.3-develop branch Related commits: 1. e2712f6 2. dec124e 3. 9e339a0 4. 334d713 5. 5c0525c 6. 73859cd 7. d30dc93 8. 661817f 9. c90d75e
2 parents 9c27244 + dd436cd commit f7d4822

File tree

8 files changed

+408
-185
lines changed

8 files changed

+408
-185
lines changed

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 46 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
<?php
22
/**
3-
*
43
* Copyright © Magento, Inc. All rights reserved.
54
* See COPYING.txt for license details.
65
*/
76

87
namespace Magento\Catalog\Model;
98

9+
use Magento\Catalog\Api\CategoryLinkManagementInterface;
1010
use Magento\Catalog\Api\Data\ProductExtension;
1111
use Magento\Catalog\Api\Data\ProductInterface;
1212
use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap;
13+
use Magento\Catalog\Model\ProductRepository\MediaGalleryProcessor;
1314
use Magento\Catalog\Model\ResourceModel\Product\Collection;
1415
use Magento\Eav\Model\Entity\Attribute\Exception as AttributeException;
15-
use Magento\Framework\Api\Data\ImageContentInterface;
1616
use Magento\Framework\Api\Data\ImageContentInterfaceFactory;
1717
use Magento\Framework\Api\ImageContentValidatorInterface;
1818
use Magento\Framework\Api\ImageProcessorInterface;
@@ -25,8 +25,8 @@
2525
use Magento\Framework\Exception\InputException;
2626
use Magento\Framework\Exception\LocalizedException;
2727
use Magento\Framework\Exception\NoSuchEntityException;
28-
use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException;
2928
use Magento\Framework\Exception\StateException;
29+
use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException;
3030
use Magento\Framework\Exception\ValidatorException;
3131

3232
/**
@@ -122,11 +122,15 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
122122
protected $fileSystem;
123123

124124
/**
125+
* @deprecated
126+
*
125127
* @var ImageContentInterfaceFactory
126128
*/
127129
protected $contentFactory;
128130

129131
/**
132+
* @deprecated
133+
*
130134
* @var ImageProcessorInterface
131135
*/
132136
protected $imageProcessor;
@@ -137,10 +141,17 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
137141
protected $extensionAttributesJoinProcessor;
138142

139143
/**
144+
* @deprecated
145+
*
140146
* @var \Magento\Catalog\Model\Product\Gallery\Processor
141147
*/
142148
protected $mediaGalleryProcessor;
143149

150+
/**
151+
* @var MediaGalleryProcessor
152+
*/
153+
private $mediaProcessor;
154+
144155
/**
145156
* @var CollectionProcessorInterface
146157
*/
@@ -161,6 +172,11 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
161172
*/
162173
private $readExtensions;
163174

175+
/**
176+
* @var CategoryLinkManagementInterface
177+
*/
178+
private $linkManagement;
179+
164180
/**
165181
* ProductRepository constructor.
166182
* @param ProductFactory $productFactory
@@ -186,7 +202,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
186202
* @param CollectionProcessorInterface $collectionProcessor [optional]
187203
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
188204
* @param int $cacheLimit [optional]
189-
* @param ReadExtensions|null $readExtensions
205+
* @param ReadExtensions $readExtensions
206+
* @param CategoryLinkManagementInterface $linkManagement
190207
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
191208
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
192209
*/
@@ -214,7 +231,8 @@ public function __construct(
214231
CollectionProcessorInterface $collectionProcessor = null,
215232
\Magento\Framework\Serialize\Serializer\Json $serializer = null,
216233
$cacheLimit = 1000,
217-
ReadExtensions $readExtensions = null
234+
ReadExtensions $readExtensions = null,
235+
CategoryLinkManagementInterface $linkManagement = null
218236
) {
219237
$this->productFactory = $productFactory;
220238
$this->collectionFactory = $collectionFactory;
@@ -239,6 +257,8 @@ public function __construct(
239257
$this->cacheLimit = (int)$cacheLimit;
240258
$this->readExtensions = $readExtensions ?: \Magento\Framework\App\ObjectManager::getInstance()
241259
->get(ReadExtensions::class);
260+
$this->linkManagement = $linkManagement ?: \Magento\Framework\App\ObjectManager::getInstance()
261+
->get(CategoryLinkManagementInterface::class);
242262
}
243263

244264
/**
@@ -381,6 +401,9 @@ private function assignProductToWebsites(\Magento\Catalog\Model\Product $product
381401
/**
382402
* Process new gallery media entry.
383403
*
404+
* @deprecated
405+
* @see MediaGalleryProcessor::processNewMediaGalleryEntry()
406+
*
384407
* @param ProductInterface $product
385408
* @param array $newEntry
386409
* @return $this
@@ -392,40 +415,8 @@ protected function processNewMediaGalleryEntry(
392415
ProductInterface $product,
393416
array $newEntry
394417
) {
395-
/** @var ImageContentInterface $contentDataObject */
396-
$contentDataObject = $newEntry['content'];
418+
$this->getMediaGalleryProcessor()->processNewMediaGalleryEntry($product, $newEntry);
397419

398-
/** @var \Magento\Catalog\Model\Product\Media\Config $mediaConfig */
399-
$mediaConfig = $product->getMediaConfig();
400-
$mediaTmpPath = $mediaConfig->getBaseTmpMediaPath();
401-
402-
$relativeFilePath = $this->imageProcessor->processImageContent($mediaTmpPath, $contentDataObject);
403-
$tmpFilePath = $mediaConfig->getTmpMediaShortUrl($relativeFilePath);
404-
405-
if (!$product->hasGalleryAttribute()) {
406-
throw new StateException(
407-
__("The product that was requested doesn't exist. Verify the product and try again.")
408-
);
409-
}
410-
411-
$imageFileUri = $this->getMediaGalleryProcessor()->addImage(
412-
$product,
413-
$tmpFilePath,
414-
isset($newEntry['types']) ? $newEntry['types'] : [],
415-
true,
416-
isset($newEntry['disabled']) ? $newEntry['disabled'] : true
417-
);
418-
// Update additional fields that are still empty after addImage call
419-
$this->getMediaGalleryProcessor()->updateImage(
420-
$product,
421-
$imageFileUri,
422-
[
423-
'label' => $newEntry['label'],
424-
'position' => $newEntry['position'],
425-
'disabled' => $newEntry['disabled'],
426-
'media_type' => $newEntry['media_type'],
427-
]
428-
);
429420
return $this;
430421
}
431422

@@ -500,68 +491,13 @@ private function processLinks(ProductInterface $product, $newLinks)
500491
* @return $this
501492
* @throws InputException
502493
* @throws StateException
494+
* @throws LocalizedException
503495
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
504496
*/
505497
protected function processMediaGallery(ProductInterface $product, $mediaGalleryEntries)
506498
{
507-
$existingMediaGallery = $product->getMediaGallery('images');
508-
$newEntries = [];
509-
$entriesById = [];
510-
if (!empty($existingMediaGallery)) {
511-
foreach ($mediaGalleryEntries as $entry) {
512-
if (isset($entry['value_id'])) {
513-
$entriesById[$entry['value_id']] = $entry;
514-
} else {
515-
$newEntries[] = $entry;
516-
}
517-
}
518-
foreach ($existingMediaGallery as $key => &$existingEntry) {
519-
if (isset($entriesById[$existingEntry['value_id']])) {
520-
$updatedEntry = $entriesById[$existingEntry['value_id']];
521-
if ($updatedEntry['file'] === null) {
522-
unset($updatedEntry['file']);
523-
}
524-
$existingMediaGallery[$key] = array_merge($existingEntry, $updatedEntry);
525-
} else {
526-
//set the removed flag
527-
$existingEntry['removed'] = true;
528-
}
529-
}
530-
$product->setData('media_gallery', ["images" => $existingMediaGallery]);
531-
} else {
532-
$newEntries = $mediaGalleryEntries;
533-
}
534-
535-
$images = (array)$product->getMediaGallery('images');
536-
$images = $this->determineImageRoles($product, $images);
537-
538-
$this->getMediaGalleryProcessor()->clearMediaAttribute($product, array_keys($product->getMediaAttributes()));
539-
540-
foreach ($images as $image) {
541-
if (!isset($image['removed']) && !empty($image['types'])) {
542-
$this->getMediaGalleryProcessor()->setMediaAttribute($product, $image['types'], $image['file']);
543-
}
544-
}
499+
$this->getMediaGalleryProcessor()->processMediaGallery($product, $mediaGalleryEntries);
545500

546-
foreach ($newEntries as $newEntry) {
547-
if (!isset($newEntry['content'])) {
548-
throw new InputException(__('The image content is invalid. Verify the content and try again.'));
549-
}
550-
/** @var ImageContentInterface $contentDataObject */
551-
$contentDataObject = $this->contentFactory->create()
552-
->setName($newEntry['content']['data'][ImageContentInterface::NAME])
553-
->setBase64EncodedData($newEntry['content']['data'][ImageContentInterface::BASE64_ENCODED_DATA])
554-
->setType($newEntry['content']['data'][ImageContentInterface::TYPE]);
555-
$newEntry['content'] = $contentDataObject;
556-
$this->processNewMediaGalleryEntry($product, $newEntry);
557-
558-
$finalGallery = $product->getData('media_gallery');
559-
$newEntryId = key(array_diff_key($product->getData('media_gallery')['images'], $entriesById));
560-
$newEntry = array_replace_recursive($newEntry, $finalGallery['images'][$newEntryId]);
561-
$entriesById[$newEntryId] = $newEntry;
562-
$finalGallery['images'][$newEntryId] = $newEntry;
563-
$product->setData('media_gallery', $finalGallery);
564-
}
565501
return $this;
566502
}
567503

@@ -572,6 +508,7 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE
572508
*/
573509
public function save(ProductInterface $product, $saveOptions = false)
574510
{
511+
$assignToCategories = false;
575512
$tierPrices = $product->getData('tier_price');
576513

577514
try {
@@ -589,6 +526,7 @@ public function save(ProductInterface $product, $saveOptions = false)
589526
$extensionAttributes = $product->getExtensionAttributes();
590527
if (empty($extensionAttributes->__toArray())) {
591528
$product->setExtensionAttributes($existingProduct->getExtensionAttributes());
529+
$assignToCategories = true;
592530
}
593531
} catch (NoSuchEntityException $e) {
594532
$existingProduct = null;
@@ -626,6 +564,12 @@ public function save(ProductInterface $product, $saveOptions = false)
626564
}
627565

628566
$this->saveProduct($product);
567+
if ($assignToCategories === true && $product->getCategoryIds()) {
568+
$this->linkManagement->assignProductToCategories(
569+
$product->getSku(),
570+
$product->getCategoryIds()
571+
);
572+
}
629573
$this->removeProductFromLocalCache($product->getSku());
630574
unset($this->instancesById[$product->getId()]);
631575

@@ -763,44 +707,19 @@ public function cleanCache()
763707
$this->instancesById = null;
764708
}
765709

766-
/**
767-
* Ascertain image roles, if they are not set against the gallery entries
768-
*
769-
* @param ProductInterface $product
770-
* @param array $images
771-
* @return array
772-
*/
773-
private function determineImageRoles(ProductInterface $product, array $images) : array
774-
{
775-
$imagesWithRoles = [];
776-
foreach ($images as $image) {
777-
if (!isset($image['types'])) {
778-
$image['types'] = [];
779-
if (isset($image['file'])) {
780-
foreach (array_keys($product->getMediaAttributes()) as $attribute) {
781-
if ($image['file'] == $product->getData($attribute)) {
782-
$image['types'][] = $attribute;
783-
}
784-
}
785-
}
786-
}
787-
$imagesWithRoles[] = $image;
788-
}
789-
return $imagesWithRoles;
790-
}
791-
792710
/**
793711
* Retrieve media gallery processor.
794712
*
795-
* @return Product\Gallery\Processor
713+
* @return MediaGalleryProcessor
796714
*/
797715
private function getMediaGalleryProcessor()
798716
{
799-
if (null === $this->mediaGalleryProcessor) {
800-
$this->mediaGalleryProcessor = \Magento\Framework\App\ObjectManager::getInstance()
801-
->get(\Magento\Catalog\Model\Product\Gallery\Processor::class);
717+
if (null === $this->mediaProcessor) {
718+
$this->mediaProcessor = \Magento\Framework\App\ObjectManager::getInstance()
719+
->get(MediaGalleryProcessor::class);
802720
}
803-
return $this->mediaGalleryProcessor;
721+
722+
return $this->mediaProcessor;
804723
}
805724

806725
/**
@@ -912,6 +831,7 @@ private function saveProduct($product): void
912831
throw new CouldNotSaveException(__($e->getMessage()));
913832
} catch (LocalizedException $e) {
914833
throw $e;
834+
// phpcs:disable Magento2.Exceptions.ThrowCatch
915835
} catch (\Exception $e) {
916836
throw new CouldNotSaveException(
917837
__('The product was unable to be saved. Please try again.'),

0 commit comments

Comments
 (0)