Skip to content

Commit 63faf82

Browse files
committed
B2B-2677: [MediaGallery]Implement data caching for GraphQL results on resolver level
- Fix overinvalidation
1 parent 2003fc9 commit 63faf82

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

app/code/Magento/CatalogGraphQl/Plugin/Product/UpdateIdentities.php

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
/**
1515
* This is a plugin to \Magento\Catalog\Model\Product.
16-
* It is to add media gallery identities to product identities.
16+
* It is used to add media gallery identities to product identities for invalidation purposes.
1717
*/
1818
class UpdateIdentities
1919
{
@@ -31,15 +31,15 @@ public function __construct(SerializerInterface $serializer)
3131
}
3232

3333
/**
34-
* Set product media gallery changed after add image to the product
34+
* Flag product media gallery as changed after adding or updating image, or on product removal
3535
*
3636
* @param Product $subject
3737
* @param array $result
3838
* @return array
3939
*/
4040
public function afterGetIdentities(Product $subject, array $result): array
4141
{
42-
if ($subject->isDeleted() || $this->isMediaGalleryChanged($subject)) {
42+
if (!$subject->isObjectNew() && ($subject->isDeleted() || $this->isMediaGalleryChanged($subject))) {
4343
$result[] = sprintf('%s_%s', ResolverCacheIdentity::CACHE_TAG, $subject->getId());
4444
}
4545
return $result;
@@ -53,12 +53,29 @@ public function afterGetIdentities(Product $subject, array $result): array
5353
*/
5454
private function isMediaGalleryChanged(Product $product): bool
5555
{
56-
$mediaGalleryImages = $product->getMediaGallery('images');
56+
if (!$product->hasDataChanges()) {
57+
return false;
58+
}
59+
60+
$mediaGalleryImages = $product->getMediaGallery('images') ?? [];
61+
62+
$origMediaGalleryImages = $product->getOrigData('media_gallery')['images'] ?? [];
63+
64+
$origMediaGalleryImageKeys = array_keys($origMediaGalleryImages);
65+
$mediaGalleryImageKeys = array_keys($mediaGalleryImages);
66+
67+
if ($origMediaGalleryImageKeys !== $mediaGalleryImageKeys) {
68+
return false;
69+
}
70+
71+
// remove keys from original array that are not in new array; some keys are omitted from the new array on save
72+
foreach ($mediaGalleryImages as $key => $mediaGalleryImage) {
73+
$origMediaGalleryImages[$key] = array_intersect_key($origMediaGalleryImages[$key], $mediaGalleryImage);
74+
}
75+
5776
$mediaGalleryImagesSerializedString = $this->serializer->serialize($mediaGalleryImages);
58-
$origMediaGallery = $product->getOrigData('media_gallery');
59-
$origMediaGalleryImages = is_array($origMediaGallery) && array_key_exists('images', $origMediaGallery)
60-
? $origMediaGallery['images'] : null;
6177
$origMediaGalleryImagesSerializedString = $this->serializer->serialize($origMediaGalleryImages);
78+
6279
return $origMediaGalleryImagesSerializedString != $mediaGalleryImagesSerializedString;
6380
}
6481
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ResolverCache/MediaGalleryTest.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,22 @@ public function testSavingProductInAdminWithoutChangesDoesNotInvalidateResolverC
104104
]);
105105

106106
$productData = $product->getData();
107+
108+
// video_* keys are not passed to the controller when saving an image
109+
foreach ($productData['media_gallery']['images'] as &$image) {
110+
$image = array_filter($image, function ($key) {
111+
return strpos($key, 'video') === false;
112+
}, ARRAY_FILTER_USE_KEY);
113+
}
114+
107115
unset($productData['entity_id']);
108116

109117
$adminProductSaveController->getRequest()->setPostValue([
110118
'id' => $product->getId(),
111119
'product' => $productData,
112120
'set' => 4, // attribute set id
113121
'type' => 'simple',
122+
'store' => 1,
114123
]);
115124

116125
$messageManager->expects($this->never())->method('addErrorMessage');
@@ -299,6 +308,12 @@ private function assertMediaGalleryResolverCacheRecordExists(ProductInterface $p
299308
{
300309
$cacheKey = $this->getCacheKeyForMediaGalleryResolver($product);
301310
$cacheEntry = $this->graphQlResolverCache->load($cacheKey);
311+
312+
$this->assertNotFalse(
313+
$cacheEntry,
314+
sprintf('Media gallery cache entry for product with sku "%s" does not exist', $product->getSku())
315+
);
316+
302317
$cacheEntryDecoded = json_decode($cacheEntry, true);
303318

304319
$this->assertEquals(
@@ -317,7 +332,8 @@ private function assertMediaGalleryResolverCacheRecordDoesNotExist(ProductInterf
317332
{
318333
$cacheKey = $this->getCacheKeyForMediaGalleryResolver($product);
319334
$this->assertFalse(
320-
$this->graphQlResolverCache->test($cacheKey)
335+
$this->graphQlResolverCache->test($cacheKey),
336+
sprintf('Media gallery cache entry for product with sku "%s" exists', $product->getSku())
321337
);
322338
}
323339

0 commit comments

Comments
 (0)