diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php
index 7927284763ecb..e69614496c66d 100644
--- a/app/code/Magento/PageCache/Controller/Block.php
+++ b/app/code/Magento/PageCache/Controller/Block.php
@@ -9,6 +9,7 @@
use Magento\Framework\Serialize\Serializer\Base64Json;
use Magento\Framework\Serialize\Serializer\Json;
+use Magento\Framework\View\Layout\LayoutCacheKeyInterface;
abstract class Block extends \Magento\Framework\App\Action\Action
{
@@ -27,17 +28,31 @@ abstract class Block extends \Magento\Framework\App\Action\Action
*/
private $base64jsonSerializer;
+ /**
+ * Layout cache keys to be able to generate different cache id for same handles
+ *
+ * @var LayoutCacheKeyInterface
+ */
+ private $layoutCacheKey;
+
+ /**
+ * @var string
+ */
+ private $layoutCacheKeyName = 'mage_pagecache';
+
/**
* @param \Magento\Framework\App\Action\Context $context
* @param \Magento\Framework\Translate\InlineInterface $translateInline
* @param Json $jsonSerializer
* @param Base64Json $base64jsonSerializer
+ * @param LayoutCacheKeyInterface $layoutCacheKey
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\Translate\InlineInterface $translateInline,
Json $jsonSerializer = null,
- Base64Json $base64jsonSerializer = null
+ Base64Json $base64jsonSerializer = null,
+ LayoutCacheKeyInterface $layoutCacheKey = null
) {
parent::__construct($context);
$this->translateInline = $translateInline;
@@ -45,6 +60,8 @@ public function __construct(
?: \Magento\Framework\App\ObjectManager::getInstance()->get(Json::class);
$this->base64jsonSerializer = $base64jsonSerializer
?: \Magento\Framework\App\ObjectManager::getInstance()->get(Base64Json::class);
+ $this->layoutCacheKey = $layoutCacheKey
+ ?: \Magento\Framework\App\ObjectManager::getInstance()->get(LayoutCacheKeyInterface::class);
}
/**
@@ -63,10 +80,12 @@ protected function _getBlocks()
$blocks = $this->jsonSerializer->unserialize($blocks);
$handles = $this->base64jsonSerializer->unserialize($handles);
+ $layout = $this->_view->getLayout();
+ $this->layoutCacheKey->addCacheKeys($this->layoutCacheKeyName);
+
$this->_view->loadLayout($handles, true, true, false);
$data = [];
- $layout = $this->_view->getLayout();
foreach ($blocks as $blockName) {
$blockInstance = $layout->getBlock($blockName);
if (is_object($blockInstance)) {
diff --git a/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php b/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php
index 4a7628c7ad839..391c827d89cb4 100644
--- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php
+++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php
@@ -39,6 +39,11 @@ class EsiTest extends \PHPUnit\Framework\TestCase
*/
protected $layoutMock;
+ /**
+ * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $layoutCacheKeyMock;
+
/**
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Translate\InlineInterface
*/
@@ -52,6 +57,8 @@ protected function setUp()
$this->layoutMock = $this->getMockBuilder(\Magento\Framework\View\Layout::class)
->disableOriginalConstructor()->getMock();
+ $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class);
+
$contextMock =
$this->getMockBuilder(\Magento\Framework\App\Action\Context::class)
->disableOriginalConstructor()->getMock();
@@ -76,7 +83,8 @@ protected function setUp()
'context' => $contextMock,
'translateInline' => $this->translateInline,
'jsonSerializer' => new \Magento\Framework\Serialize\Serializer\Json(),
- 'base64jsonSerializer' => new \Magento\Framework\Serialize\Serializer\Base64Json()
+ 'base64jsonSerializer' => new \Magento\Framework\Serialize\Serializer\Base64Json(),
+ 'layoutCacheKey' => $this->layoutCacheKeyMock
]
);
}
@@ -104,6 +112,11 @@ public function testExecute($blockClass, $shouldSetHeaders)
$this->viewMock->expects($this->once())->method('getLayout')->will($this->returnValue($this->layoutMock));
+ $this->layoutMock->expects($this->never())
+ ->method('getUpdate');
+ $this->layoutCacheKeyMock->expects($this->atLeastOnce())
+ ->method('addCacheKeys');
+
$this->layoutMock->expects($this->once())
->method('getBlock')
->with($this->equalTo($block))
diff --git a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php
index 2b55a93473180..6c46aa7d29fa0 100644
--- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php
+++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php
@@ -44,14 +44,26 @@ class RenderTest extends \PHPUnit\Framework\TestCase
*/
protected $layoutMock;
+ /**
+ * @var \Magento\Framework\View\Layout\ProcessorInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $layoutProcessorMock;
+
+ /**
+ * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $layoutCacheKeyMock;
+
/**
* Set up before test
*/
protected function setUp()
{
- $this->layoutMock = $this->getMockBuilder(
- \Magento\Framework\View\Layout::class
- )->disableOriginalConstructor()->getMock();
+ $this->layoutMock = $this->getMockBuilder(\Magento\Framework\View\Layout::class)
+ ->disableOriginalConstructor()->getMock();
+
+ $this->layoutProcessorMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\ProcessorInterface::class);
+ $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class);
$contextMock = $this->getMockBuilder(\Magento\Framework\App\Action\Context::class)
->disableOriginalConstructor()->getMock();
@@ -65,6 +77,8 @@ protected function setUp()
$this->viewMock = $this->getMockBuilder(\Magento\Framework\App\View::class)
->disableOriginalConstructor()->getMock();
+ $this->layoutMock->expects($this->any())->method('getUpdate')->will($this->returnValue($this->layoutProcessorMock));
+
$contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->requestMock));
$contextMock->expects($this->any())->method('getResponse')->will($this->returnValue($this->responseMock));
$contextMock->expects($this->any())->method('getView')->will($this->returnValue($this->viewMock));
@@ -78,7 +92,8 @@ protected function setUp()
'context' => $contextMock,
'translateInline' => $this->translateInline,
'jsonSerializer' => new \Magento\Framework\Serialize\Serializer\Json(),
- 'base64jsonSerializer' => new \Magento\Framework\Serialize\Serializer\Base64Json()
+ 'base64jsonSerializer' => new \Magento\Framework\Serialize\Serializer\Base64Json(),
+ 'layoutCacheKey' => $this->layoutCacheKeyMock
]
);
}
@@ -88,6 +103,8 @@ public function testExecuteNotAjax()
$this->requestMock->expects($this->once())->method('isAjax')->will($this->returnValue(false));
$this->requestMock->expects($this->once())->method('setActionName')->will($this->returnValue('noroute'));
$this->requestMock->expects($this->once())->method('setDispatched')->will($this->returnValue(false));
+ $this->layoutCacheKeyMock->expects($this->never())
+ ->method('addCacheKeys');
$this->action->execute();
}
@@ -105,6 +122,8 @@ public function testExecuteNoParams()
->method('getParam')
->with($this->equalTo('handles'), $this->equalTo(''))
->will($this->returnValue(''));
+ $this->layoutCacheKeyMock->expects($this->never())
+ ->method('addCacheKeys');
$this->action->execute();
}
@@ -150,6 +169,10 @@ public function testExecute()
->will($this->returnValue(base64_encode(json_encode($handles))));
$this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($handles));
$this->viewMock->expects($this->any())->method('getLayout')->will($this->returnValue($this->layoutMock));
+ $this->layoutMock->expects($this->never())
+ ->method('getUpdate');
+ $this->layoutCacheKeyMock->expects($this->atLeastOnce())
+ ->method('addCacheKeys');
$this->layoutMock->expects($this->at(0))
->method('getBlock')
->with($this->equalTo($blocks[0]))
diff --git a/app/code/Magento/PageCache/etc/di.xml b/app/code/Magento/PageCache/etc/di.xml
index 92daefe046213..2a9abbb860805 100644
--- a/app/code/Magento/PageCache/etc/di.xml
+++ b/app/code/Magento/PageCache/etc/di.xml
@@ -32,6 +32,11 @@
+
+
+ Magento\Framework\View\Layout\LayoutCacheKeyInterface
+
+
diff --git a/app/etc/di.xml b/app/etc/di.xml
index e17505e78da31..33e27305b78b9 100755
--- a/app/etc/di.xml
+++ b/app/etc/di.xml
@@ -68,6 +68,7 @@
+
@@ -740,6 +741,7 @@
Magento\Framework\View\Layout\File\Collector\Aggregated\Proxy
pageLayoutFileCollectorAggregated
Magento\Framework\App\Cache\Type\Layout
+ Magento\Framework\View\Layout\LayoutCacheKeyInterface
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php
index 3ba43f7142e82..8404884a7cf5c 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php
@@ -7,6 +7,7 @@
use Magento\Framework\App\State;
use Magento\Framework\Phrase;
+use Magento\Framework\View\Layout\LayoutCacheKeyInterface;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -65,6 +66,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase
*/
protected $pageConfig;
+ /**
+ * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $layoutCacheKeyMock;
+
protected function setUp()
{
$files = [];
@@ -119,6 +125,11 @@ function ($filename) use ($fileDriver) {
)
);
+ $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class);
+ $this->layoutCacheKeyMock->expects($this->any())
+ ->method('getCacheKeys')
+ ->willReturn([]);
+
$this->_model = $objectHelper->getObject(
\Magento\Framework\View\Model\Layout\Merge::class,
[
@@ -134,6 +145,7 @@ function ($filename) use ($fileDriver) {
'logger' => $this->_logger,
'readFactory' => $readFactory,
'pageConfig' => $this->pageConfig,
+ 'layoutCacheKey' => $this->layoutCacheKeyMock,
]
);
}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Model/Layout/MergeTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Model/Layout/MergeTest.php
index ede1b33296ea4..12c8b1990fbbe 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/Model/Layout/MergeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/Model/Layout/MergeTest.php
@@ -5,6 +5,8 @@
*/
namespace Magento\Framework\View\Model\Layout;
+use Magento\Framework\View\Layout\LayoutCacheKeyInterface;
+
class MergeTest extends \PHPUnit\Framework\TestCase
{
/**
@@ -18,6 +20,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase
*/
protected $model;
+ /**
+ * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $layoutCacheKeyMock;
+
protected function setUp()
{
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
@@ -62,9 +69,17 @@ protected function setUp()
$link2->setLayoutUpdateId($layoutUpdate2->getId());
$link2->save();
+ $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class);
+ $this->layoutCacheKeyMock->expects($this->any())
+ ->method('getCacheKeys')
+ ->willReturn([]);
+
$this->model = $objectManager->create(
\Magento\Framework\View\Model\Layout\Merge::class,
- ['theme' => $theme]
+ [
+ 'theme' => $theme,
+ 'layoutCacheKey' => $this->layoutCacheKeyMock,
+ ]
);
}
diff --git a/lib/internal/Magento/Framework/View/Layout/LayoutCacheKeyInterface.php b/lib/internal/Magento/Framework/View/Layout/LayoutCacheKeyInterface.php
new file mode 100644
index 0000000000000..1d4bb8aebe882
--- /dev/null
+++ b/lib/internal/Magento/Framework/View/Layout/LayoutCacheKeyInterface.php
@@ -0,0 +1,27 @@
+cacheKeys = array_merge($this->cacheKeys, $cacheKeys);
+ }
+
+ /**
+ * Return cache keys array
+ *
+ * @return array
+ */
+ public function getCacheKeys()
+ {
+ return $this->cacheKeys;
+ }
+}
diff --git a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php
index 97cbeb83a7a86..ea8f74107954c 100644
--- a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php
+++ b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php
@@ -9,6 +9,7 @@
use Magento\Framework\Config\Dom\ValidationException;
use Magento\Framework\Filesystem\DriverPool;
use Magento\Framework\Filesystem\File\ReadFactory;
+use Magento\Framework\View\Layout\LayoutCacheKeyInterface;
use Magento\Framework\View\Model\Layout\Update\Validator;
/**
@@ -103,6 +104,13 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
*/
private $appState;
+ /**
+ * Cache keys to be able to generate different cache id for same handles
+ *
+ * @var LayoutCacheKeyInterface
+ */
+ private $layoutCacheKey;
+
/**
* @var \Magento\Framework\Cache\FrontendInterface
*/
@@ -165,9 +173,10 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface
* @param \Magento\Framework\Cache\FrontendInterface $cache
* @param \Magento\Framework\View\Model\Layout\Update\Validator $validator
* @param \Psr\Log\LoggerInterface $logger
- * @param ReadFactory $readFactory,
+ * @param ReadFactory $readFactory ,
* @param \Magento\Framework\View\Design\ThemeInterface $theme Non-injectable theme instance
* @param string $cacheSuffix
+ * @param LayoutCacheKeyInterface $layoutCacheKey
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -181,7 +190,8 @@ public function __construct(
\Psr\Log\LoggerInterface $logger,
ReadFactory $readFactory,
\Magento\Framework\View\Design\ThemeInterface $theme = null,
- $cacheSuffix = ''
+ $cacheSuffix = '',
+ LayoutCacheKeyInterface $layoutCacheKey = null
) {
$this->theme = $theme ?: $design->getDesignTheme();
$this->scope = $scopeResolver->getScope();
@@ -193,6 +203,8 @@ public function __construct(
$this->logger = $logger;
$this->readFactory = $readFactory;
$this->cacheSuffix = $cacheSuffix;
+ $this->layoutCacheKey = $layoutCacheKey
+ ?: \Magento\Framework\App\ObjectManager::getInstance()->get(LayoutCacheKeyInterface::class);
}
/**
@@ -715,7 +727,7 @@ protected function _loadFileLayoutUpdatesXml()
$updateFiles = array_merge($updateFiles, $this->pageLayoutFileSource->getFiles($theme, '*.xml'));
$useErrors = libxml_use_internal_errors(true);
foreach ($updateFiles as $file) {
- /** @var $fileReader \Magento\Framework\Filesystem\File\Read */
+ /** @var $fileReader \Magento\Framework\Filesystem\File\Read */
$fileReader = $this->readFactory->create($file->getFilename(), DriverPool::FILE);
$fileStr = $fileReader->readAll($file->getName());
$fileStr = $this->_substitutePlaceholders($fileStr);
@@ -914,6 +926,7 @@ public function getScope()
*/
public function getCacheId()
{
- return $this->generateCacheId(md5(implode('|', $this->getHandles())));
+ $layoutCacheKeys = $this->layoutCacheKey->getCacheKeys();
+ return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $layoutCacheKeys))));
}
}
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php
index 0cb3254e818a3..112d171f2574b 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php
@@ -9,6 +9,7 @@
use Magento\Framework\Config\Dom\ValidationSchemaException;
use Magento\Framework\Phrase;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Framework\View\Layout\LayoutCacheKeyInterface;
class MergeTest extends \PHPUnit\Framework\TestCase
{
@@ -42,6 +43,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase
*/
private $appState;
+ /**
+ * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $layoutCacheKeyMock;
+
protected function setUp()
{
$this->objectManagerHelper = new ObjectManager($this);
@@ -55,6 +61,11 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
+ $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class);
+ $this->layoutCacheKeyMock->expects($this->any())
+ ->method('getCacheKeys')
+ ->willReturn([]);
+
$this->model = $this->objectManagerHelper->getObject(
\Magento\Framework\View\Model\Layout\Merge::class,
[
@@ -62,6 +73,7 @@ protected function setUp()
'layoutValidator' => $this->layoutValidator,
'logger' => $this->logger,
'appState' => $this->appState,
+ 'layoutCacheKey' => $this->layoutCacheKeyMock,
]
);
}