88
99namespace Magento \Catalog \Model \Product \Gallery ;
1010
11+ use Magento \Catalog \Api \Data \ProductAttributeMediaGalleryEntryInterface ;
1112use Magento \Catalog \Api \Data \ProductInterface ;
1213use Magento \Catalog \Api \ProductRepositoryInterface ;
1314use Magento \Catalog \Model \Product ;
1415use Magento \Catalog \Model \Product \Media \Config ;
1516use Magento \Catalog \Model \ResourceModel \Product as ProductResource ;
1617use Magento \Catalog \Model \ResourceModel \Product \Gallery ;
1718use Magento \Framework \App \Filesystem \DirectoryList ;
19+ use Magento \Framework \EntityManager \MetadataPool ;
1820use Magento \Framework \Filesystem ;
1921use Magento \Framework \Filesystem \Directory \WriteInterface ;
2022use Magento \Framework \ObjectManagerInterface ;
@@ -84,11 +86,17 @@ class UpdateHandlerTest extends \PHPUnit\Framework\TestCase
8486 * @var StoreManagerInterface
8587 */
8688 private $ storeManager ;
89+
8790 /**
8891 * @var int
8992 */
9093 private $ currentStoreId ;
9194
95+ /**
96+ * @var MetadataPool
97+ */
98+ private $ metadataPool ;
99+
92100 /**
93101 * @inheritdoc
94102 */
@@ -108,6 +116,7 @@ protected function setUp(): void
108116 $ this ->mediaDirectory = $ this ->objectManager ->get (Filesystem::class)
109117 ->getDirectoryWrite (DirectoryList::MEDIA );
110118 $ this ->mediaDirectory ->writeFile ($ this ->fileName , 'Test ' );
119+ $ this ->metadataPool = $ this ->objectManager ->get (MetadataPool::class);
111120 }
112121
113122 /**
@@ -351,6 +360,23 @@ public function testExecuteWithTwoImagesOnStoreView(): void
351360 }
352361 }
353362
363+ /**
364+ * @magentoDataFixture Magento/Catalog/_files/product_with_image.php
365+ * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php
366+ *
367+ * @return void
368+ */
369+ public function testDeleteSharedImage (): void
370+ {
371+ $ product = $ this ->getProduct (null , 'simple ' );
372+ $ this ->duplicateMediaGalleryForProduct ('/m/a/magento_image.jpg ' , 'simple2 ' );
373+ $ secondProduct = $ this ->getProduct (null , 'simple2 ' );
374+ $ this ->updateHandler ->execute ($ this ->prepareRemoveImage ($ product ), []);
375+ $ product = $ this ->getProduct (null , 'simple ' );
376+ $ this ->assertEmpty ($ product ->getMediaGalleryImages ()->getItems ());
377+ $ this ->checkProductImageExist ($ secondProduct , '/m/a/magento_image.jpg ' );
378+ }
379+
354380 /**
355381 * @inheritdoc
356382 */
@@ -371,11 +397,13 @@ protected function tearDown(): void
371397 * Returns current product.
372398 *
373399 * @param int|null $storeId
400+ * @param string|null $sku
374401 * @return ProductInterface|Product
375402 */
376- private function getProduct (?int $ storeId = null ): ProductInterface
403+ private function getProduct (?int $ storeId = null , ? string $ sku = null ): ProductInterface
377404 {
378- return $ this ->productRepository ->get ('simple ' , false , $ storeId , true );
405+ $ sku = $ sku ?: 'simple ' ;
406+ return $ this ->productRepository ->get ($ sku , false , $ storeId , true );
379407 }
380408
381409 /**
@@ -464,6 +492,86 @@ public function testDeleteWithMultiWebsites(): void
464492 $ this ->assertArrayNotHasKey ($ secondStoreId , $ imageRolesPerStore );
465493 }
466494
495+ /**
496+ * Check product image link and product image exist
497+ *
498+ * @param ProductInterface $product
499+ * @param string $imagePath
500+ * @return void
501+ */
502+ private function checkProductImageExist (ProductInterface $ product , string $ imagePath ): void
503+ {
504+ $ productImageItem = $ product ->getMediaGalleryImages ()->getFirstItem ();
505+ $ this ->assertEquals ($ imagePath , $ productImageItem ->getFile ());
506+ $ productImageFile = $ productImageItem ->getPath ();
507+ $ this ->assertNotEmpty ($ productImageFile );
508+ $ this ->assertTrue ($ this ->mediaDirectory ->getDriver ()->isExists ($ productImageFile ));
509+ $ this ->fileName = $ productImageFile ;
510+ }
511+
512+ /**
513+ * Prepare the product to remove image
514+ *
515+ * @param ProductInterface $product
516+ * @return ProductInterface
517+ */
518+ private function prepareRemoveImage (ProductInterface $ product ): ProductInterface
519+ {
520+ $ item = $ product ->getMediaGalleryImages ()->getFirstItem ();
521+ $ item ->setRemoved ('1 ' );
522+ $ galleryData = [
523+ 'images ' => [
524+ (int )$ item ->getValueId () => $ item ->getData (),
525+ ]
526+ ];
527+ $ product ->setData (ProductInterface::MEDIA_GALLERY , $ galleryData );
528+ $ product ->setStoreId (0 );
529+
530+ return $ product ;
531+ }
532+
533+ /**
534+ * Duplicate media gallery entries for a product
535+ *
536+ * @param string $imagePath
537+ * @param string $productSku
538+ * @return void
539+ */
540+ private function duplicateMediaGalleryForProduct (string $ imagePath , string $ productSku ): void
541+ {
542+ $ product = $ this ->getProduct (null , $ productSku );
543+ $ connect = $ this ->galleryResource ->getConnection ();
544+ $ select = $ connect ->select ()->from ($ this ->galleryResource ->getMainTable ())->where ('value = ? ' , $ imagePath );
545+ $ result = $ connect ->fetchRow ($ select );
546+ $ value_id = $ result ['value_id ' ];
547+ unset($ result ['value_id ' ]);
548+ $ rows = [
549+ 'attribute_id ' => $ result ['attribute_id ' ],
550+ 'value ' => $ result ['value ' ],
551+ ProductAttributeMediaGalleryEntryInterface::MEDIA_TYPE => $ result ['media_type ' ],
552+ ProductAttributeMediaGalleryEntryInterface::DISABLED => $ result ['disabled ' ],
553+ ];
554+ $ connect ->insert ($ this ->galleryResource ->getMainTable (), $ rows );
555+ $ select = $ connect ->select ()
556+ ->from ($ this ->galleryResource ->getTable (Gallery::GALLERY_VALUE_TABLE ))
557+ ->where ('value_id = ? ' , $ value_id );
558+ $ result = $ connect ->fetchRow ($ select );
559+ $ newValueId = (int )$ value_id + 1 ;
560+ $ metadata = $ this ->metadataPool ->getMetadata (ProductInterface::class);
561+ $ linkField = $ metadata ->getLinkField ();
562+ $ rows = [
563+ 'value_id ' => $ newValueId ,
564+ 'store_id ' => $ result ['store_id ' ],
565+ ProductAttributeMediaGalleryEntryInterface::LABEL => $ result ['label ' ],
566+ ProductAttributeMediaGalleryEntryInterface::POSITION => $ result ['position ' ],
567+ ProductAttributeMediaGalleryEntryInterface::DISABLED => $ result ['disabled ' ],
568+ $ linkField => $ product ->getData ($ linkField ),
569+ ];
570+ $ connect ->insert ($ this ->galleryResource ->getTable (Gallery::GALLERY_VALUE_TABLE ), $ rows );
571+ $ rows = ['value_id ' => $ newValueId , $ linkField => $ product ->getData ($ linkField )];
572+ $ connect ->insert ($ this ->galleryResource ->getTable (Gallery::GALLERY_VALUE_TO_ENTITY_TABLE ), $ rows );
573+ }
574+
467575 /**
468576 * @param Product $product
469577 * @param array $roles
0 commit comments