77
88namespace Magento \Catalog \Model ;
99
10+ use Magento \Catalog \Api \Data \ProductExtension ;
1011use Magento \Catalog \Api \Data \ProductInterface ;
1112use Magento \Catalog \Model \Product \Gallery \MimeTypeExtensionMap ;
1213use Magento \Catalog \Model \ResourceModel \Product \Collection ;
14+ use Magento \Eav \Model \Entity \Attribute \Exception as AttributeException ;
1315use Magento \Framework \Api \Data \ImageContentInterface ;
1416use Magento \Framework \Api \Data \ImageContentInterfaceFactory ;
1517use Magento \Framework \Api \ImageContentValidatorInterface ;
2224use Magento \Framework \Exception \InputException ;
2325use Magento \Framework \Exception \LocalizedException ;
2426use Magento \Framework \Exception \NoSuchEntityException ;
27+ use Magento \Framework \Exception \TemporaryState \CouldNotSaveException as TemporaryCouldNotSaveException ;
2528use Magento \Framework \Exception \StateException ;
2629use Magento \Framework \Exception \ValidatorException ;
2730
@@ -306,10 +309,10 @@ protected function getCacheKey($data)
306309 * Add product to internal cache and truncate cache if it has more than cacheLimit elements.
307310 *
308311 * @param string $cacheKey
309- * @param \Magento\Catalog\Api\Data\ ProductInterface $product
312+ * @param ProductInterface $product
310313 * @return void
311314 */
312- private function cacheProduct ($ cacheKey , \ Magento \ Catalog \ Api \ Data \ ProductInterface $ product )
315+ private function cacheProduct ($ cacheKey , ProductInterface $ product )
313316 {
314317 $ this ->instancesById [$ product ->getId ()][$ cacheKey ] = $ product ;
315318 $ this ->saveProductInLocalCache ($ product , $ cacheKey );
@@ -326,7 +329,7 @@ private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterf
326329 *
327330 * @param array $productData
328331 * @param bool $createNew
329- * @return \Magento\Catalog\Api\Data\ ProductInterface|Product
332+ * @return ProductInterface|Product
330333 * @throws NoSuchEntityException
331334 */
332335 protected function initializeProductData (array $ productData , $ createNew )
@@ -414,12 +417,12 @@ protected function processNewMediaGalleryEntry(
414417 /**
415418 * Process product links, creating new links, updating and deleting existing links
416419 *
417- * @param \Magento\Catalog\Api\Data\ ProductInterface $product
420+ * @param ProductInterface $product
418421 * @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $newLinks
419422 * @return $this
420423 * @throws NoSuchEntityException
421424 */
422- private function processLinks (\ Magento \ Catalog \ Api \ Data \ ProductInterface $ product , $ newLinks )
425+ private function processLinks (ProductInterface $ product , $ newLinks )
423426 {
424427 if ($ newLinks === null ) {
425428 // If product links were not specified, don't do anything
@@ -548,11 +551,11 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE
548551 }
549552
550553 /**
551- * { @inheritdoc}
554+ * @inheritdoc
552555 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
553556 * @SuppressWarnings(PHPMD.NPathComplexity)
554557 */
555- public function save (\ Magento \ Catalog \ Api \ Data \ ProductInterface $ product , $ saveOptions = false )
558+ public function save (ProductInterface $ product , $ saveOptions = false )
556559 {
557560 $ tierPrices = $ product ->getData ('tier_price ' );
558561
@@ -566,12 +569,18 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
566569 if (!$ product ->hasData (Product::STATUS )) {
567570 $ product ->setStatus ($ existingProduct ->getStatus ());
568571 }
572+
573+ /** @var ProductExtension $extensionAttributes */
574+ $ extensionAttributes = $ product ->getExtensionAttributes ();
575+ if (empty ($ extensionAttributes ->__toArray ())) {
576+ $ product ->setExtensionAttributes ($ existingProduct ->getExtensionAttributes ());
577+ }
569578 } catch (NoSuchEntityException $ e ) {
570579 $ existingProduct = null ;
571580 }
572581
573582 $ productDataArray = $ this ->extensibleDataObjectConverter
574- ->toNestedArray ($ product , [], \ Magento \ Catalog \ Api \ Data \ ProductInterface::class);
583+ ->toNestedArray ($ product , [], ProductInterface::class);
575584 $ productDataArray = array_replace ($ productDataArray , $ product ->getData ());
576585 $ ignoreLinksFlag = $ product ->getData ('ignore_links_flag ' );
577586 $ productLinks = null ;
@@ -597,47 +606,11 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
597606 );
598607 }
599608
600- try {
601- if ($ tierPrices !== null ) {
602- $ product ->setData ('tier_price ' , $ tierPrices );
603- }
604- $ this ->removeProductFromLocalCache ($ product ->getSku ());
605- unset($ this ->instancesById [$ product ->getId ()]);
606- $ this ->resourceModel ->save ($ product );
607- } catch (ConnectionException $ exception ) {
608- throw new \Magento \Framework \Exception \TemporaryState \CouldNotSaveException (
609- __ ('Database connection error ' ),
610- $ exception ,
611- $ exception ->getCode ()
612- );
613- } catch (DeadlockException $ exception ) {
614- throw new \Magento \Framework \Exception \TemporaryState \CouldNotSaveException (
615- __ ('Database deadlock found when trying to get lock ' ),
616- $ exception ,
617- $ exception ->getCode ()
618- );
619- } catch (LockWaitException $ exception ) {
620- throw new \Magento \Framework \Exception \TemporaryState \CouldNotSaveException (
621- __ ('Database lock wait timeout exceeded ' ),
622- $ exception ,
623- $ exception ->getCode ()
624- );
625- } catch (\Magento \Eav \Model \Entity \Attribute \Exception $ exception ) {
626- throw \Magento \Framework \Exception \InputException::invalidFieldValue (
627- $ exception ->getAttributeCode (),
628- $ product ->getData ($ exception ->getAttributeCode ()),
629- $ exception
630- );
631- } catch (ValidatorException $ e ) {
632- throw new CouldNotSaveException (__ ($ e ->getMessage ()));
633- } catch (LocalizedException $ e ) {
634- throw $ e ;
635- } catch (\Exception $ e ) {
636- throw new \Magento \Framework \Exception \CouldNotSaveException (
637- __ ('The product was unable to be saved. Please try again. ' ),
638- $ e
639- );
609+ if ($ tierPrices !== null ) {
610+ $ product ->setData ('tier_price ' , $ tierPrices );
640611 }
612+
613+ $ this ->saveProduct ($ product );
641614 $ this ->removeProductFromLocalCache ($ product ->getSku ());
642615 unset($ this ->instancesById [$ product ->getId ()]);
643616
@@ -647,7 +620,7 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
647620 /**
648621 * {@inheritdoc}
649622 */
650- public function delete (\ Magento \ Catalog \ Api \ Data \ ProductInterface $ product )
623+ public function delete (ProductInterface $ product )
651624 {
652625 $ sku = $ product ->getSku ();
653626 $ productId = $ product ->getId ();
@@ -862,4 +835,55 @@ private function prepareSku(string $sku): string
862835 {
863836 return mb_strtolower (trim ($ sku ));
864837 }
838+
839+ /**
840+ * Save product resource model.
841+ *
842+ * @param ProductInterface|Product $product
843+ * @throws TemporaryCouldNotSaveException
844+ * @throws InputException
845+ * @throws CouldNotSaveException
846+ * @throws LocalizedException
847+ */
848+ private function saveProduct ($ product ): void
849+ {
850+ try {
851+ $ this ->removeProductFromLocalCache ($ product ->getSku ());
852+ unset($ this ->instancesById [$ product ->getId ()]);
853+ $ this ->resourceModel ->save ($ product );
854+ } catch (ConnectionException $ exception ) {
855+ throw new TemporaryCouldNotSaveException (
856+ __ ('Database connection error ' ),
857+ $ exception ,
858+ $ exception ->getCode ()
859+ );
860+ } catch (DeadlockException $ exception ) {
861+ throw new TemporaryCouldNotSaveException (
862+ __ ('Database deadlock found when trying to get lock ' ),
863+ $ exception ,
864+ $ exception ->getCode ()
865+ );
866+ } catch (LockWaitException $ exception ) {
867+ throw new TemporaryCouldNotSaveException (
868+ __ ('Database lock wait timeout exceeded ' ),
869+ $ exception ,
870+ $ exception ->getCode ()
871+ );
872+ } catch (AttributeException $ exception ) {
873+ throw InputException::invalidFieldValue (
874+ $ exception ->getAttributeCode (),
875+ $ product ->getData ($ exception ->getAttributeCode ()),
876+ $ exception
877+ );
878+ } catch (ValidatorException $ e ) {
879+ throw new CouldNotSaveException (__ ($ e ->getMessage ()));
880+ } catch (LocalizedException $ e ) {
881+ throw $ e ;
882+ } catch (\Exception $ e ) {
883+ throw new CouldNotSaveException (
884+ __ ('The product was unable to be saved. Please try again. ' ),
885+ $ e
886+ );
887+ }
888+ }
865889}
0 commit comments