66 */
77namespace Magento \Catalog \Model ;
88
9+ use Magento \Catalog \Api \Data \ProductExtension ;
10+ use Magento \Catalog \Api \Data \ProductInterface ;
911use Magento \Catalog \Model \Product \Gallery \MimeTypeExtensionMap ;
1012use Magento \Catalog \Model \ResourceModel \Product \Collection ;
13+ use Magento \Eav \Model \Entity \Attribute \Exception as AttributeException ;
1114use Magento \Framework \Api \Data \ImageContentInterfaceFactory ;
1215use Magento \Framework \Api \ImageContentValidatorInterface ;
1316use Magento \Framework \Api \ImageProcessorInterface ;
1619use Magento \Framework \DB \Adapter \DeadlockException ;
1720use Magento \Framework \DB \Adapter \LockWaitException ;
1821use Magento \Framework \Exception \CouldNotSaveException ;
22+ use Magento \Framework \Exception \InputException ;
1923use Magento \Framework \Exception \LocalizedException ;
2024use Magento \Framework \Exception \NoSuchEntityException ;
25+ use Magento \Framework \Exception \TemporaryState \CouldNotSaveException as TemporaryCouldNotSaveException ;
2126use Magento \Framework \Exception \ValidatorException ;
2227
2328/**
@@ -294,10 +299,10 @@ protected function getCacheKey($data)
294299 * Add product to internal cache and truncate cache if it has more than cacheLimit elements.
295300 *
296301 * @param string $cacheKey
297- * @param \Magento\Catalog\Api\Data\ ProductInterface $product
302+ * @param ProductInterface $product
298303 * @return void
299304 */
300- private function cacheProduct ($ cacheKey , \ Magento \ Catalog \ Api \ Data \ ProductInterface $ product )
305+ private function cacheProduct ($ cacheKey , ProductInterface $ product )
301306 {
302307 $ this ->instancesById [$ product ->getId ()][$ cacheKey ] = $ product ;
303308 $ this ->saveProductInLocalCache ($ product , $ cacheKey );
@@ -314,7 +319,7 @@ private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterf
314319 *
315320 * @param array $productData
316321 * @param bool $createNew
317- * @return \Magento\Catalog\Api\Data\ ProductInterface|Product
322+ * @return ProductInterface|Product
318323 * @throws NoSuchEntityException
319324 */
320325 protected function initializeProductData (array $ productData , $ createNew )
@@ -361,12 +366,12 @@ private function assignProductToWebsites(\Magento\Catalog\Model\Product $product
361366 /**
362367 * Process product links, creating new links, updating and deleting existing links
363368 *
364- * @param \Magento\Catalog\Api\Data\ ProductInterface $product
369+ * @param ProductInterface $product
365370 * @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $newLinks
366371 * @return $this
367372 * @throws NoSuchEntityException
368373 */
369- private function processLinks (\ Magento \ Catalog \ Api \ Data \ ProductInterface $ product , $ newLinks )
374+ private function processLinks (ProductInterface $ product , $ newLinks )
370375 {
371376 if ($ newLinks === null ) {
372377 // If product links were not specified, don't do anything
@@ -421,7 +426,7 @@ private function processLinks(\Magento\Catalog\Api\Data\ProductInterface $produc
421426 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
422427 * @SuppressWarnings(PHPMD.NPathComplexity)
423428 */
424- public function save (\ Magento \ Catalog \ Api \ Data \ ProductInterface $ product , $ saveOptions = false )
429+ public function save (ProductInterface $ product , $ saveOptions = false )
425430 {
426431 $ tierPrices = $ product ->getData ('tier_price ' );
427432
@@ -435,12 +440,18 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
435440 if (!$ product ->hasData (Product::STATUS )) {
436441 $ product ->setStatus ($ existingProduct ->getStatus ());
437442 }
443+
444+ /** @var ProductExtension $extensionAttributes */
445+ $ extensionAttributes = $ product ->getExtensionAttributes ();
446+ if (empty ($ extensionAttributes ->__toArray ())) {
447+ $ product ->setExtensionAttributes ($ existingProduct ->getExtensionAttributes ());
448+ }
438449 } catch (NoSuchEntityException $ e ) {
439450 $ existingProduct = null ;
440451 }
441452
442453 $ productDataArray = $ this ->extensibleDataObjectConverter
443- ->toNestedArray ($ product , [], \ Magento \ Catalog \ Api \ Data \ ProductInterface::class);
454+ ->toNestedArray ($ product , [], ProductInterface::class);
444455 $ productDataArray = array_replace ($ productDataArray , $ product ->getData ());
445456 $ ignoreLinksFlag = $ product ->getData ('ignore_links_flag ' );
446457 $ productLinks = null ;
@@ -471,53 +482,21 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
471482 );
472483 }
473484
474- try {
475- if ($ tierPrices !== null ) {
476- $ product ->setData ('tier_price ' , $ tierPrices );
477- }
478- $ this ->removeProductFromLocalCache ($ product ->getSku ());
479- unset($ this ->instancesById [$ product ->getId ()]);
480- $ this ->resourceModel ->save ($ product );
481- } catch (ConnectionException $ exception ) {
482- throw new \Magento \Framework \Exception \TemporaryState \CouldNotSaveException (
483- __ ('Database connection error ' ),
484- $ exception ,
485- $ exception ->getCode ()
486- );
487- } catch (DeadlockException $ exception ) {
488- throw new \Magento \Framework \Exception \TemporaryState \CouldNotSaveException (
489- __ ('Database deadlock found when trying to get lock ' ),
490- $ exception ,
491- $ exception ->getCode ()
492- );
493- } catch (LockWaitException $ exception ) {
494- throw new \Magento \Framework \Exception \TemporaryState \CouldNotSaveException (
495- __ ('Database lock wait timeout exceeded ' ),
496- $ exception ,
497- $ exception ->getCode ()
498- );
499- } catch (\Magento \Eav \Model \Entity \Attribute \Exception $ exception ) {
500- throw \Magento \Framework \Exception \InputException::invalidFieldValue (
501- $ exception ->getAttributeCode (),
502- $ product ->getData ($ exception ->getAttributeCode ()),
503- $ exception
504- );
505- } catch (ValidatorException $ e ) {
506- throw new CouldNotSaveException (__ ($ e ->getMessage ()));
507- } catch (LocalizedException $ e ) {
508- throw $ e ;
509- } catch (\Exception $ e ) {
510- throw new \Magento \Framework \Exception \CouldNotSaveException (__ ('Unable to save product ' ), $ e );
485+ if ($ tierPrices !== null ) {
486+ $ product ->setData ('tier_price ' , $ tierPrices );
511487 }
488+
489+ $ this ->saveProduct ($ product );
512490 $ this ->removeProductFromLocalCache ($ product ->getSku ());
513491 unset($ this ->instancesById [$ product ->getId ()]);
492+
514493 return $ this ->get ($ product ->getSku (), false , $ product ->getStoreId ());
515494 }
516495
517496 /**
518497 * {@inheritdoc}
519498 */
520- public function delete (\ Magento \ Catalog \ Api \ Data \ ProductInterface $ product )
499+ public function delete (ProductInterface $ product )
521500 {
522501 $ sku = $ product ->getSku ();
523502 $ productId = $ product ->getId ();
@@ -707,4 +686,52 @@ private function prepareSku(string $sku): string
707686 {
708687 return mb_strtolower (trim ($ sku ));
709688 }
689+
690+ /**
691+ * Save product resource model.
692+ *
693+ * @param ProductInterface|Product $product
694+ * @throws TemporaryCouldNotSaveException
695+ * @throws InputException
696+ * @throws CouldNotSaveException
697+ * @throws LocalizedException
698+ */
699+ private function saveProduct ($ product )
700+ {
701+ try {
702+ $ this ->removeProductFromLocalCache ($ product ->getSku ());
703+ unset($ this ->instancesById [$ product ->getId ()]);
704+ $ this ->resourceModel ->save ($ product );
705+ } catch (ConnectionException $ exception ) {
706+ throw new TemporaryCouldNotSaveException (
707+ __ ('Database connection error ' ),
708+ $ exception ,
709+ $ exception ->getCode ()
710+ );
711+ } catch (DeadlockException $ exception ) {
712+ throw new TemporaryCouldNotSaveException (
713+ __ ('Database deadlock found when trying to get lock ' ),
714+ $ exception ,
715+ $ exception ->getCode ()
716+ );
717+ } catch (LockWaitException $ exception ) {
718+ throw new TemporaryCouldNotSaveException (
719+ __ ('Database lock wait timeout exceeded ' ),
720+ $ exception ,
721+ $ exception ->getCode ()
722+ );
723+ } catch (AttributeException $ exception ) {
724+ throw InputException::invalidFieldValue (
725+ $ exception ->getAttributeCode (),
726+ $ product ->getData ($ exception ->getAttributeCode ()),
727+ $ exception
728+ );
729+ } catch (ValidatorException $ e ) {
730+ throw new CouldNotSaveException (__ ($ e ->getMessage ()));
731+ } catch (LocalizedException $ e ) {
732+ throw $ e ;
733+ } catch (\Exception $ e ) {
734+ throw new CouldNotSaveException (__ ('Unable to save product ' ), $ e );
735+ }
736+ }
710737}
0 commit comments