Add page cache tags to the infinite scroll AJAX response

There's a bug in the Mirasvit infinite scroll module, the AJAX response does not contain any cache tags. This means
that when Magento sends cache clean commands to Varnish the paginated scroll responses are not cleared from Varnish.

This patch addresses the bug and makes sure the X-Magento-Tags header is sent with the response containing the
category & product IDs.

https://www.wrike.com/open.htm?id=1335474022

--- ./vendor/mirasvit/module-navigation/src/Scroll/Plugin/Frontend/ScrollResponsePlugin.php
+++ ./vendor/mirasvit/module-navigation/src/Scroll/Plugin/Frontend/ScrollResponsePlugin.php
@@ -22,6 +22,7 @@ use Magento\Framework\App\RequestInterface;
 use Magento\Framework\App\ResponseInterface;
 use Magento\Framework\View\Element\BlockInterface;
 use Magento\Framework\View\LayoutInterface;
+use Magento\PageCache\Model\Config;
 use Mirasvit\Scroll\Model\ConfigProvider;
 
 /**
@@ -41,6 +42,7 @@ class ScrollResponsePlugin
 
     public function __construct(
         ConfigProvider $config,
+        private readonly Config $pageCacheConfig,
         RequestInterface $request,
         ResponseInterface $response,
         LayoutInterface $layout
@@ -72,10 +74,16 @@ class ScrollResponsePlugin
 
         $products = $this->getProductListBlock();
 
-        return $this->response->representJson(\Zend_Json::encode([
+        $responseData = [
             'products' => $products ? $products->toHtml() : '',
             'config'   => $scrollBlock->getJsConfig(),
-        ]));
+        ];
+
+        if ($products) {
+            $this->setPageCacheHeaders($products); // must not be called before $products->toHtml()
+        }
+
+        return $this->response->representJson(\Zend_Json::encode($responseData));
     }
 
     private function canProcess(): bool
@@ -97,4 +105,27 @@ class ScrollResponsePlugin
 
         return $block ? $block : null;
     }
+
+    private function setPageCacheHeaders(BlockInterface $products): void
+    {
+        $tags = [];
+
+        if (method_exists($products, 'getIdentities')) {
+            $tags = $products->getIdentities();
+        }
+
+        $productsList = $products->getChildBlock('product_list');
+        if ($productsList && method_exists($productsList, 'getLoadedProductCollection')) {
+            foreach ($productsList->getLoadedProductCollection() as $product) {
+                if (method_exists($product, 'getIdentities')) {
+                    $tags = array_merge($tags, $product->getIdentities());
+                }
+            }
+        }
+
+        $tags = array_unique($tags);
+
+        $this->response->setPublicHeaders($this->pageCacheConfig->getTtl());
+        $this->response->setHeader('X-Magento-Tags', implode(',', $tags));
+    }
 }
