From 3bdfa1b6fb8d516b22fb3bf9cc18bf86ba11331f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 May 2017 13:31:08 +0200 Subject: [PATCH 01/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 --- app/code/Magento/PageCache/Controller/Block.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index 7927284763ecb..5d4473d5472ec 100644 --- a/app/code/Magento/PageCache/Controller/Block.php +++ b/app/code/Magento/PageCache/Controller/Block.php @@ -27,6 +27,11 @@ abstract class Block extends \Magento\Framework\App\Action\Action */ private $base64jsonSerializer; + /** + * @var string + */ + private $additionalPageCacheHandle = 'additional_page_cache_handle'; + /** * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Framework\Translate\InlineInterface $translateInline @@ -63,6 +68,8 @@ protected function _getBlocks() $blocks = $this->jsonSerializer->unserialize($blocks); $handles = $this->base64jsonSerializer->unserialize($handles); + $handles[] = $this->additionalPageCacheHandle; + $this->_view->loadLayout($handles, true, true, false); $data = []; From 5a6a000c2cca5dc1f18eb872f1ff584ccd795d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 May 2017 14:00:12 +0200 Subject: [PATCH 02/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 --- app/code/Magento/PageCache/Controller/Block.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index 5d4473d5472ec..1e13f4b8be41f 100644 --- a/app/code/Magento/PageCache/Controller/Block.php +++ b/app/code/Magento/PageCache/Controller/Block.php @@ -68,7 +68,9 @@ protected function _getBlocks() $blocks = $this->jsonSerializer->unserialize($blocks); $handles = $this->base64jsonSerializer->unserialize($handles); - $handles[] = $this->additionalPageCacheHandle; + if(is_array($handles)){ + $handles[] = $this->additionalPageCacheHandle; + } $this->_view->loadLayout($handles, true, true, false); $data = []; From bf7df0d8800f843ce2abd70c527fa901f90474fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 May 2017 15:27:18 +0200 Subject: [PATCH 03/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 Fix PSR-2 standard --- app/code/Magento/PageCache/Controller/Block.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index 1e13f4b8be41f..63feba3ecaa40 100644 --- a/app/code/Magento/PageCache/Controller/Block.php +++ b/app/code/Magento/PageCache/Controller/Block.php @@ -68,7 +68,7 @@ protected function _getBlocks() $blocks = $this->jsonSerializer->unserialize($blocks); $handles = $this->base64jsonSerializer->unserialize($handles); - if(is_array($handles)){ + if (is_array($handles)) { $handles[] = $this->additionalPageCacheHandle; } From 7feba6c4921eb934bd69d64332ed7957c3750fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 May 2017 15:27:50 +0200 Subject: [PATCH 04/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 Adapted page cache tests --- .../PageCache/Test/Unit/Controller/Block/EsiTest.php | 8 +++++--- .../PageCache/Test/Unit/Controller/Block/RenderTest.php | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) 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 da448993bf3c9..ddbb70b11d297 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php @@ -89,9 +89,11 @@ protected function setUp() public function testExecute($blockClass, $shouldSetHeaders) { $block = 'block'; - $handles = ['handle1', 'handle2']; + $requestHandles = ['handle1', 'handle2']; + $additionalPageCacheHandle = 'additional_page_cache_handle'; + $pageCacheHandles = array_merge($requestHandles, [$additionalPageCacheHandle]); $html = 'some-html'; - $mapData = [['blocks', '', json_encode([$block])], ['handles', '', base64_encode(json_encode($handles))]]; + $mapData = [['blocks', '', json_encode([$block])], ['handles', '', base64_encode(json_encode($requestHandles))]]; $blockInstance1 = $this->getMock( $blockClass, @@ -106,7 +108,7 @@ public function testExecute($blockClass, $shouldSetHeaders) $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($mapData)); - $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($handles)); + $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($pageCacheHandles)); $this->viewMock->expects($this->once())->method('getLayout')->will($this->returnValue($this->layoutMock)); 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 a54877715a0ec..18ba862f7fd0a 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php @@ -111,7 +111,10 @@ public function testExecuteNoParams() public function testExecute() { $blocks = ['block1', 'block2']; - $handles = ['handle1', 'handle2']; + $requestHandles = ['handle1', 'handle2']; + $additionalPageCacheHandle = 'additional_page_cache_handle'; + $pageCacheHandles = array_merge($requestHandles, [$additionalPageCacheHandle]); + $originalRequest = '{"route":"route","controller":"controller","action":"action","uri":"uri"}'; $expectedData = ['block1' => 'data1', 'block2' => 'data2']; @@ -159,8 +162,8 @@ public function testExecute() $this->requestMock->expects($this->at(11)) ->method('getParam') ->with($this->equalTo('handles'), $this->equalTo('')) - ->will($this->returnValue(base64_encode(json_encode($handles)))); - $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($handles)); + ->will($this->returnValue(base64_encode(json_encode($requestHandles)))); + $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($pageCacheHandles)); $this->viewMock->expects($this->any())->method('getLayout')->will($this->returnValue($this->layoutMock)); $this->layoutMock->expects($this->at(0)) ->method('getBlock') From 1bb25ed56967e3a0f8d8b98909c300b59209348a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 10 May 2017 12:29:24 +0200 Subject: [PATCH 05/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 Update additional pagecache layout handle name --- app/code/Magento/PageCache/Controller/Block.php | 2 +- .../Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php | 2 +- .../Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index 63feba3ecaa40..1721f9dcae9fd 100644 --- a/app/code/Magento/PageCache/Controller/Block.php +++ b/app/code/Magento/PageCache/Controller/Block.php @@ -30,7 +30,7 @@ abstract class Block extends \Magento\Framework\App\Action\Action /** * @var string */ - private $additionalPageCacheHandle = 'additional_page_cache_handle'; + private $additionalPageCacheHandle = 'mage_pagecache_additional_handle'; /** * @param \Magento\Framework\App\Action\Context $context 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 ddbb70b11d297..6e427eb2d9cf5 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php @@ -90,7 +90,7 @@ public function testExecute($blockClass, $shouldSetHeaders) { $block = 'block'; $requestHandles = ['handle1', 'handle2']; - $additionalPageCacheHandle = 'additional_page_cache_handle'; + $additionalPageCacheHandle = 'mage_pagecache_additional_handle'; $pageCacheHandles = array_merge($requestHandles, [$additionalPageCacheHandle]); $html = 'some-html'; $mapData = [['blocks', '', json_encode([$block])], ['handles', '', base64_encode(json_encode($requestHandles))]]; 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 18ba862f7fd0a..735b4412d3ff6 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php @@ -112,7 +112,7 @@ public function testExecute() { $blocks = ['block1', 'block2']; $requestHandles = ['handle1', 'handle2']; - $additionalPageCacheHandle = 'additional_page_cache_handle'; + $additionalPageCacheHandle = 'mage_pagecache_additional_handle'; $pageCacheHandles = array_merge($requestHandles, [$additionalPageCacheHandle]); $originalRequest = '{"route":"route","controller":"controller","action":"action","uri":"uri"}'; From 0e830c1829a958774eb2c72891b6de6dba76d9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 17 May 2017 02:21:14 +0200 Subject: [PATCH 06/14] Fix PageCache: async rendering of blocks can corrupt layout cache Refactored original solution, implemented cache keys for layout to be able to generate different unique cache ids also based on possibly added cache keys --- .../Magento/PageCache/Controller/Block.php | 8 +-- .../Test/Unit/Controller/Block/EsiTest.php | 24 +++++-- .../Test/Unit/Controller/Block/RenderTest.php | 31 +++++++--- app/etc/env.php.original | 62 +++++++++++++++++++ .../View/Layout/ProcessorInterface.php | 10 ++- .../Framework/View/Model/Layout/Merge.php | 26 +++++++- 6 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 app/etc/env.php.original diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index 1721f9dcae9fd..b4fc8bcd79482 100644 --- a/app/code/Magento/PageCache/Controller/Block.php +++ b/app/code/Magento/PageCache/Controller/Block.php @@ -30,7 +30,7 @@ abstract class Block extends \Magento\Framework\App\Action\Action /** * @var string */ - private $additionalPageCacheHandle = 'mage_pagecache_additional_handle'; + private $layoutCacheKey = 'mage_pagecache'; /** * @param \Magento\Framework\App\Action\Context $context @@ -68,14 +68,12 @@ protected function _getBlocks() $blocks = $this->jsonSerializer->unserialize($blocks); $handles = $this->base64jsonSerializer->unserialize($handles); - if (is_array($handles)) { - $handles[] = $this->additionalPageCacheHandle; - } + $layout = $this->_view->getLayout(); + $layout->getUpdate()->addCacheKey($this->layoutCacheKey); $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 6e427eb2d9cf5..a7c4de2575ce5 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\ProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutProcessorMock; + /** * @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->layoutProcessorMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\ProcessorInterface::class); + $contextMock = $this->getMockBuilder(\Magento\Framework\App\Action\Context::class) ->disableOriginalConstructor()->getMock(); @@ -63,6 +70,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)); @@ -89,11 +98,9 @@ protected function setUp() public function testExecute($blockClass, $shouldSetHeaders) { $block = 'block'; - $requestHandles = ['handle1', 'handle2']; - $additionalPageCacheHandle = 'mage_pagecache_additional_handle'; - $pageCacheHandles = array_merge($requestHandles, [$additionalPageCacheHandle]); + $handles = ['handle1', 'handle2']; $html = 'some-html'; - $mapData = [['blocks', '', json_encode([$block])], ['handles', '', base64_encode(json_encode($requestHandles))]]; + $mapData = [['blocks', '', json_encode([$block])], ['handles', '', base64_encode(json_encode($handles))]]; $blockInstance1 = $this->getMock( $blockClass, @@ -108,10 +115,17 @@ public function testExecute($blockClass, $shouldSetHeaders) $this->requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($mapData)); - $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($pageCacheHandles)); + $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($handles)); $this->viewMock->expects($this->once())->method('getLayout')->will($this->returnValue($this->layoutMock)); + $this->layoutMock->expects($this->at(0)) + ->method('getUpdate') + ->will($this->returnValue($this->layoutProcessorMock)); + $this->layoutProcessorMock->expects($this->at(0)) + ->method('addCacheKey') + ->willReturnSelf(); + $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 735b4412d3ff6..e2337f5615121 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,20 @@ class RenderTest extends \PHPUnit_Framework_TestCase */ protected $layoutMock; + /** + * @var \Magento\Framework\View\Layout\ProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutProcessorMock; + /** * 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); $contextMock = $this->getMockBuilder(\Magento\Framework\App\Action\Context::class) ->disableOriginalConstructor()->getMock(); @@ -65,6 +71,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)); @@ -111,10 +119,7 @@ public function testExecuteNoParams() public function testExecute() { $blocks = ['block1', 'block2']; - $requestHandles = ['handle1', 'handle2']; - $additionalPageCacheHandle = 'mage_pagecache_additional_handle'; - $pageCacheHandles = array_merge($requestHandles, [$additionalPageCacheHandle]); - + $handles = ['handle1', 'handle2']; $originalRequest = '{"route":"route","controller":"controller","action":"action","uri":"uri"}'; $expectedData = ['block1' => 'data1', 'block2' => 'data2']; @@ -162,14 +167,20 @@ public function testExecute() $this->requestMock->expects($this->at(11)) ->method('getParam') ->with($this->equalTo('handles'), $this->equalTo('')) - ->will($this->returnValue(base64_encode(json_encode($requestHandles)))); - $this->viewMock->expects($this->once())->method('loadLayout')->with($this->equalTo($pageCacheHandles)); + ->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->at(0)) + ->method('getUpdate') + ->will($this->returnValue($this->layoutProcessorMock)); + $this->layoutProcessorMock->expects($this->at(0)) + ->method('addCacheKey') + ->willReturnSelf(); + $this->layoutMock->expects($this->at(1)) ->method('getBlock') ->with($this->equalTo($blocks[0])) ->will($this->returnValue($blockInstance1)); - $this->layoutMock->expects($this->at(1)) + $this->layoutMock->expects($this->at(2)) ->method('getBlock') ->with($this->equalTo($blocks[1])) ->will($this->returnValue($blockInstance2)); diff --git a/app/etc/env.php.original b/app/etc/env.php.original new file mode 100644 index 0000000000000..74a48ba9db8ee --- /dev/null +++ b/app/etc/env.php.original @@ -0,0 +1,62 @@ + + array ( + 'frontName' => 'suadmin', + ), + 'crypt' => + array ( + 'key' => '5b2bd4f91709ea56ce8a0b1bc00b67a0', + ), + 'session' => + array ( + 'save' => 'files', + ), + 'db' => + array ( + 'table_prefix' => '', + 'connection' => + array ( + 'default' => + array ( + 'host' => 'localhost', + 'dbname' => 'mg2develop', + 'username' => 'zend', + 'password' => '', + 'model' => 'mysql4', + 'engine' => 'innodb', + 'initStatements' => 'SET NAMES utf8;', + 'active' => '1', + ), + ), + ), + 'resource' => + array ( + 'default_setup' => + array ( + 'connection' => 'default', + ), + ), + 'x-frame-options' => 'SAMEORIGIN', + 'MAGE_MODE' => 'default', + 'cache_types' => + array ( + 'config' => 1, + 'layout' => 1, + 'block_html' => 1, + 'collections' => 1, + 'reflection' => 1, + 'db_ddl' => 1, + 'eav' => 1, + 'customer_notification' => 1, + 'config_integration' => 1, + 'config_integration_api' => 1, + 'full_page' => 1, + 'translate' => 1, + 'config_webservice' => 1, + ), + 'install' => + array ( + 'date' => 'Mon, 08 May 2017 23:53:11 +0000', + ), +); diff --git a/lib/internal/Magento/Framework/View/Layout/ProcessorInterface.php b/lib/internal/Magento/Framework/View/Layout/ProcessorInterface.php index eb4771b1b89d8..0c2f050f9d83e 100644 --- a/lib/internal/Magento/Framework/View/Layout/ProcessorInterface.php +++ b/lib/internal/Magento/Framework/View/Layout/ProcessorInterface.php @@ -126,7 +126,15 @@ public function getFileLayoutUpdatesXml(); public function getContainers(); /** - * Return cache ID based current area/package/theme/store and handles + * Add cache key for generating different cache id for same handles + * + * @param array|string $cacheKey + * @return ProcessorInterface + */ + public function addCacheKey($cacheKey); + + /** + * Return cache ID based current area/package/theme/store, handles and cache key(s) * * @return string */ diff --git a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php index 97cbeb83a7a86..a4174aafd1947 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\ProcessorInterface; use Magento\Framework\View\Model\Layout\Update\Validator; /** @@ -128,6 +129,13 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface */ protected $cacheSuffix; + /** + * Cache keys to be able to generate different cache id for same handles + * + * @var array + */ + protected $cacheKeys = []; + /** * All processed handles used in this update * @@ -907,6 +915,22 @@ public function getScope() return $this->scope; } + /** + * Add cache key(s) for generating different cache id for same handles + * + * @param array|string $cacheKeys + * @return $this + */ + public function addCacheKey($cacheKeys) + { + if (!is_array($cacheKeys)) { + $cacheKeys = [$cacheKeys]; + } + $this->cacheKeys = array_merge($this->cacheKeys, $cacheKeys); + + return $this; + } + /** * Return cache ID based current area/package/theme/store and handles * @@ -914,6 +938,6 @@ public function getScope() */ public function getCacheId() { - return $this->generateCacheId(md5(implode('|', $this->getHandles()))); + return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $this->cacheKeys)))); } } From 8a92e46826cfd36ce2ee69eaa9e9a089c5a05162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 17 May 2017 02:25:35 +0200 Subject: [PATCH 07/14] Fix PageCache: async rendering of blocks can corrupt layout cache Refactored original solution, implemented cache keys for layout to be able to generate different unique cache ids also based on possibly added cache keys --- app/etc/env.php.original | 62 ---------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 app/etc/env.php.original diff --git a/app/etc/env.php.original b/app/etc/env.php.original deleted file mode 100644 index 74a48ba9db8ee..0000000000000 --- a/app/etc/env.php.original +++ /dev/null @@ -1,62 +0,0 @@ - - array ( - 'frontName' => 'suadmin', - ), - 'crypt' => - array ( - 'key' => '5b2bd4f91709ea56ce8a0b1bc00b67a0', - ), - 'session' => - array ( - 'save' => 'files', - ), - 'db' => - array ( - 'table_prefix' => '', - 'connection' => - array ( - 'default' => - array ( - 'host' => 'localhost', - 'dbname' => 'mg2develop', - 'username' => 'zend', - 'password' => '', - 'model' => 'mysql4', - 'engine' => 'innodb', - 'initStatements' => 'SET NAMES utf8;', - 'active' => '1', - ), - ), - ), - 'resource' => - array ( - 'default_setup' => - array ( - 'connection' => 'default', - ), - ), - 'x-frame-options' => 'SAMEORIGIN', - 'MAGE_MODE' => 'default', - 'cache_types' => - array ( - 'config' => 1, - 'layout' => 1, - 'block_html' => 1, - 'collections' => 1, - 'reflection' => 1, - 'db_ddl' => 1, - 'eav' => 1, - 'customer_notification' => 1, - 'config_integration' => 1, - 'config_integration_api' => 1, - 'full_page' => 1, - 'translate' => 1, - 'config_webservice' => 1, - ), - 'install' => - array ( - 'date' => 'Mon, 08 May 2017 23:53:11 +0000', - ), -); From bd6ed7c473f4271ba7b6e2dfaad6b65aac9e8c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 21 Sep 2017 18:28:39 +0200 Subject: [PATCH 08/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Create cache key object to be injected separately with its own interface --- .../Magento/PageCache/Controller/Block.php | 14 ++++++- app/etc/di.xml | 1 + .../View/Layout/CacheKeyInterface.php | 26 ++++++++++++ .../View/Layout/ProcessorInterface.php | 8 ---- .../Framework/View/Model/Layout/CacheKey.php | 41 +++++++++++++++++++ .../Framework/View/Model/Layout/Merge.php | 38 ++++++----------- 6 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php create mode 100644 lib/internal/Magento/Framework/View/Model/Layout/CacheKey.php diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index b4fc8bcd79482..6a5a502e6d570 100644 --- a/app/code/Magento/PageCache/Controller/Block.php +++ b/app/code/Magento/PageCache/Controller/Block.php @@ -27,6 +27,13 @@ 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 \Magento\Framework\View\Layout\CacheKeyInterface + */ + private $cacheKey; + /** * @var string */ @@ -37,12 +44,14 @@ abstract class Block extends \Magento\Framework\App\Action\Action * @param \Magento\Framework\Translate\InlineInterface $translateInline * @param Json $jsonSerializer * @param Base64Json $base64jsonSerializer + * @param \Magento\Framework\View\Layout\CacheKeyInterface $cacheKey */ public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Framework\Translate\InlineInterface $translateInline, Json $jsonSerializer = null, - Base64Json $base64jsonSerializer = null + Base64Json $base64jsonSerializer = null, + \Magento\Framework\View\Layout\CacheKeyInterface $cacheKey ) { parent::__construct($context); $this->translateInline = $translateInline; @@ -50,6 +59,7 @@ public function __construct( ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Json::class); $this->base64jsonSerializer = $base64jsonSerializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Base64Json::class); + $this->cacheKey = $cacheKey; } /** @@ -69,7 +79,7 @@ protected function _getBlocks() $handles = $this->base64jsonSerializer->unserialize($handles); $layout = $this->_view->getLayout(); - $layout->getUpdate()->addCacheKey($this->layoutCacheKey); + $this->cacheKey->addCacheKey($this->layoutCacheKey); $this->_view->loadLayout($handles, true, true, false); $data = []; diff --git a/app/etc/di.xml b/app/etc/di.xml index e17505e78da31..84c74fd42dd07 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -68,6 +68,7 @@ + diff --git a/lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php b/lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php new file mode 100644 index 0000000000000..a0bb31c7c4f98 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php @@ -0,0 +1,26 @@ +cacheKeys = array_merge($this->cacheKeys, $cacheKeys); + } + + /** + * Return cache keys array stored + * + * @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 a4174aafd1947..e365464d0a59a 100644 --- a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php +++ b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php @@ -9,7 +9,6 @@ use Magento\Framework\Config\Dom\ValidationException; use Magento\Framework\Filesystem\DriverPool; use Magento\Framework\Filesystem\File\ReadFactory; -use Magento\Framework\View\Layout\ProcessorInterface; use Magento\Framework\View\Model\Layout\Update\Validator; /** @@ -104,6 +103,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 \Magento\Framework\View\Layout\CacheKeyInterface + */ + private $cacheKey; + /** * @var \Magento\Framework\Cache\FrontendInterface */ @@ -129,13 +135,6 @@ class Merge implements \Magento\Framework\View\Layout\ProcessorInterface */ protected $cacheSuffix; - /** - * Cache keys to be able to generate different cache id for same handles - * - * @var array - */ - protected $cacheKeys = []; - /** * All processed handles used in this update * @@ -173,8 +172,9 @@ 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 \Magento\Framework\View\Layout\CacheKeyInterface $cacheKey * @param string $cacheSuffix * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -189,6 +189,7 @@ public function __construct( \Psr\Log\LoggerInterface $logger, ReadFactory $readFactory, \Magento\Framework\View\Design\ThemeInterface $theme = null, + \Magento\Framework\View\Layout\CacheKeyInterface $cacheKey, $cacheSuffix = '' ) { $this->theme = $theme ?: $design->getDesignTheme(); @@ -200,6 +201,7 @@ public function __construct( $this->layoutValidator = $validator; $this->logger = $logger; $this->readFactory = $readFactory; + $this->cacheKey = $cacheKey; $this->cacheSuffix = $cacheSuffix; } @@ -915,22 +917,6 @@ public function getScope() return $this->scope; } - /** - * Add cache key(s) for generating different cache id for same handles - * - * @param array|string $cacheKeys - * @return $this - */ - public function addCacheKey($cacheKeys) - { - if (!is_array($cacheKeys)) { - $cacheKeys = [$cacheKeys]; - } - $this->cacheKeys = array_merge($this->cacheKeys, $cacheKeys); - - return $this; - } - /** * Return cache ID based current area/package/theme/store and handles * @@ -938,6 +924,6 @@ public function addCacheKey($cacheKeys) */ public function getCacheId() { - return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $this->cacheKeys)))); + return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $this->cacheKey->getCacheKeys())))); } } From c6e2b399166ede65bc2c19cc7ed83d35b371b01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 22 Sep 2017 02:36:39 +0200 Subject: [PATCH 09/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Renamed interface, LayoutCacheKeyInterface made optional in constructor, injected via di.xml, some other little fixes --- .../Magento/PageCache/Controller/Block.php | 16 ++++++----- app/code/Magento/PageCache/etc/di.xml | 5 ++++ app/etc/di.xml | 3 ++- .../View/Layout/CacheKeyInterface.php | 26 ------------------ .../View/Layout/LayoutCacheKeyInterface.php | 27 +++++++++++++++++++ .../Framework/View/Model/Layout/CacheKey.php | 7 ++--- .../Framework/View/Model/Layout/Merge.php | 16 ++++++----- 7 files changed, 56 insertions(+), 44 deletions(-) delete mode 100644 lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php create mode 100644 lib/internal/Magento/Framework/View/Layout/LayoutCacheKeyInterface.php diff --git a/app/code/Magento/PageCache/Controller/Block.php b/app/code/Magento/PageCache/Controller/Block.php index 6a5a502e6d570..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 { @@ -30,28 +31,28 @@ abstract class Block extends \Magento\Framework\App\Action\Action /** * Layout cache keys to be able to generate different cache id for same handles * - * @var \Magento\Framework\View\Layout\CacheKeyInterface + * @var LayoutCacheKeyInterface */ - private $cacheKey; + private $layoutCacheKey; /** * @var string */ - private $layoutCacheKey = 'mage_pagecache'; + private $layoutCacheKeyName = 'mage_pagecache'; /** * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Framework\Translate\InlineInterface $translateInline * @param Json $jsonSerializer * @param Base64Json $base64jsonSerializer - * @param \Magento\Framework\View\Layout\CacheKeyInterface $cacheKey + * @param LayoutCacheKeyInterface $layoutCacheKey */ public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Framework\Translate\InlineInterface $translateInline, Json $jsonSerializer = null, Base64Json $base64jsonSerializer = null, - \Magento\Framework\View\Layout\CacheKeyInterface $cacheKey + LayoutCacheKeyInterface $layoutCacheKey = null ) { parent::__construct($context); $this->translateInline = $translateInline; @@ -59,7 +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->cacheKey = $cacheKey; + $this->layoutCacheKey = $layoutCacheKey + ?: \Magento\Framework\App\ObjectManager::getInstance()->get(LayoutCacheKeyInterface::class); } /** @@ -79,7 +81,7 @@ protected function _getBlocks() $handles = $this->base64jsonSerializer->unserialize($handles); $layout = $this->_view->getLayout(); - $this->cacheKey->addCacheKey($this->layoutCacheKey); + $this->layoutCacheKey->addCacheKeys($this->layoutCacheKeyName); $this->_view->loadLayout($handles, true, true, false); $data = []; 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 84c74fd42dd07..33e27305b78b9 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -68,7 +68,7 @@ - + @@ -741,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/lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php b/lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php deleted file mode 100644 index a0bb31c7c4f98..0000000000000 --- a/lib/internal/Magento/Framework/View/Layout/CacheKeyInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -theme = $theme ?: $design->getDesignTheme(); $this->scope = $scopeResolver->getScope(); @@ -201,8 +202,9 @@ public function __construct( $this->layoutValidator = $validator; $this->logger = $logger; $this->readFactory = $readFactory; - $this->cacheKey = $cacheKey; $this->cacheSuffix = $cacheSuffix; + $this->layoutCacheKey = $layoutCacheKey + ?: \Magento\Framework\App\ObjectManager::getInstance()->get(LayoutCacheKeyInterface::class); } /** @@ -924,6 +926,6 @@ public function getScope() */ public function getCacheId() { - return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $this->cacheKey->getCacheKeys())))); + return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $this->layoutCacheKey->getCacheKeys())))); } } From 3cc51dce1100da3baa0cdee041b1ae0320cae506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 22 Sep 2017 03:28:59 +0200 Subject: [PATCH 10/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Adapted PageCache and Framework tests --- .../Test/Unit/Controller/Block/EsiTest.php | 21 +++++++--------- .../Test/Unit/Controller/Block/RenderTest.php | 25 +++++++++++++------ .../View/Test/Unit/Model/Layout/MergeTest.php | 10 ++++++++ 3 files changed, 36 insertions(+), 20 deletions(-) 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 c781d94afbe8c..391c827d89cb4 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/EsiTest.php @@ -40,9 +40,9 @@ class EsiTest extends \PHPUnit\Framework\TestCase protected $layoutMock; /** - * @var \Magento\Framework\View\Layout\ProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $layoutProcessorMock; + protected $layoutCacheKeyMock; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Translate\InlineInterface @@ -57,7 +57,7 @@ protected function setUp() $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) @@ -70,8 +70,6 @@ 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)); @@ -85,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 ] ); } @@ -113,12 +112,10 @@ public function testExecute($blockClass, $shouldSetHeaders) $this->viewMock->expects($this->once())->method('getLayout')->will($this->returnValue($this->layoutMock)); - $this->layoutMock->expects($this->at(0)) - ->method('getUpdate') - ->will($this->returnValue($this->layoutProcessorMock)); - $this->layoutProcessorMock->expects($this->at(0)) - ->method('addCacheKey') - ->willReturnSelf(); + $this->layoutMock->expects($this->never()) + ->method('getUpdate'); + $this->layoutCacheKeyMock->expects($this->atLeastOnce()) + ->method('addCacheKeys'); $this->layoutMock->expects($this->once()) ->method('getBlock') 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 b110b1b8a573b..6c46aa7d29fa0 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php @@ -49,6 +49,11 @@ class RenderTest extends \PHPUnit\Framework\TestCase */ protected $layoutProcessorMock; + /** + * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutCacheKeyMock; + /** * Set up before test */ @@ -58,6 +63,7 @@ protected function setUp() ->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(); @@ -86,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 ] ); } @@ -96,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(); } @@ -113,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(); } @@ -158,17 +169,15 @@ 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('getUpdate') - ->will($this->returnValue($this->layoutProcessorMock)); - $this->layoutProcessorMock->expects($this->at(0)) - ->method('addCacheKey') - ->willReturnSelf(); - $this->layoutMock->expects($this->at(1)) ->method('getBlock') ->with($this->equalTo($blocks[0])) ->will($this->returnValue($blockInstance1)); - $this->layoutMock->expects($this->at(2)) + $this->layoutMock->expects($this->at(1)) ->method('getBlock') ->with($this->equalTo($blocks[1])) ->will($this->returnValue($blockInstance2)); 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..6f1ca59850ca4 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 @@ -42,6 +42,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase */ private $appState; + /** + * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutCacheKeyMock; + protected function setUp() { $this->objectManagerHelper = new ObjectManager($this); @@ -54,6 +59,7 @@ protected function setUp() $this->appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->getMock(); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class); $this->model = $this->objectManagerHelper->getObject( \Magento\Framework\View\Model\Layout\Merge::class, @@ -62,6 +68,7 @@ protected function setUp() 'layoutValidator' => $this->layoutValidator, 'logger' => $this->logger, 'appState' => $this->appState, + 'layoutCacheKey' => $this->layoutCacheKeyMock ] ); } @@ -76,6 +83,9 @@ public function testValidateMergedLayoutThrowsException() 'Please correct the XSD data and try again.', ]; $this->scope->expects($this->once())->method('getId')->willReturn(1); + $this->layoutCacheKeyMock->expects($this->once()) + ->method('getCacheKeys') + ->willReturn([]); $this->layoutValidator->expects($this->once()) ->method('isValid') ->willThrowException( From 2ae9c26b836b791d02fad1d4bd8222da7a275143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 22 Sep 2017 13:34:57 +0200 Subject: [PATCH 11/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Adapted PageCache and Framework tests --- .../Magento/Framework/View/Layout/MergeTest.php | 11 +++++++++++ .../Framework/View/Model/Layout/MergeTest.php | 15 ++++++++++++++- .../View/Test/Unit/Model/Layout/MergeTest.php | 9 +++++---- 3 files changed, 30 insertions(+), 5 deletions(-) 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..b2275014618b9 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/Layout/MergeTest.php @@ -65,6 +65,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase */ protected $pageConfig; + /** + * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutCacheKeyMock; + protected function setUp() { $files = []; @@ -119,6 +124,11 @@ function ($filename) use ($fileDriver) { ) ); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class); + $this->layoutCacheKeyMock->expects($this->any()) + ->method('getCacheKeys') + ->willReturn([]); + $this->_model = $objectHelper->getObject( \Magento\Framework\View\Model\Layout\Merge::class, [ @@ -134,6 +144,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..153ce6d25b6b6 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 @@ -18,6 +18,11 @@ class MergeTest extends \PHPUnit\Framework\TestCase */ protected $model; + /** + * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutCacheKeyMock; + protected function setUp() { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -62,9 +67,17 @@ protected function setUp() $link2->setLayoutUpdateId($layoutUpdate2->getId()); $link2->save(); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\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/Test/Unit/Model/Layout/MergeTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/MergeTest.php index 6f1ca59850ca4..36841d2a74d50 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 @@ -59,7 +59,11 @@ protected function setUp() $this->appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->getMock(); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class); + $this->layoutCacheKeyMock->expects($this->any()) + ->method('getCacheKeys') + ->willReturn([]); $this->model = $this->objectManagerHelper->getObject( \Magento\Framework\View\Model\Layout\Merge::class, @@ -68,7 +72,7 @@ protected function setUp() 'layoutValidator' => $this->layoutValidator, 'logger' => $this->logger, 'appState' => $this->appState, - 'layoutCacheKey' => $this->layoutCacheKeyMock + 'layoutCacheKey' => $this->layoutCacheKeyMock, ] ); } @@ -83,9 +87,6 @@ public function testValidateMergedLayoutThrowsException() 'Please correct the XSD data and try again.', ]; $this->scope->expects($this->once())->method('getId')->willReturn(1); - $this->layoutCacheKeyMock->expects($this->once()) - ->method('getCacheKeys') - ->willReturn([]); $this->layoutValidator->expects($this->once()) ->method('isValid') ->willThrowException( From 516b5295a271a53853f31afa8de0508e8fefcff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 22 Sep 2017 13:38:03 +0200 Subject: [PATCH 12/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Adapted PageCache and Framework tests --- .../testsuite/Magento/Framework/View/Layout/MergeTest.php | 5 +++-- .../Magento/Framework/View/Model/Layout/MergeTest.php | 6 ++++-- .../Magento/Framework/View/Model/Layout/CacheKey.php | 3 ++- .../Framework/View/Test/Unit/Model/Layout/MergeTest.php | 5 +++-- 4 files changed, 12 insertions(+), 7 deletions(-) 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 b2275014618b9..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) @@ -66,7 +67,7 @@ class MergeTest extends \PHPUnit\Framework\TestCase protected $pageConfig; /** - * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $layoutCacheKeyMock; @@ -124,7 +125,7 @@ function ($filename) use ($fileDriver) { ) ); - $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class); $this->layoutCacheKeyMock->expects($this->any()) ->method('getCacheKeys') ->willReturn([]); 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 153ce6d25b6b6..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 { /** @@ -19,7 +21,7 @@ class MergeTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $layoutCacheKeyMock; @@ -67,7 +69,7 @@ protected function setUp() $link2->setLayoutUpdateId($layoutUpdate2->getId()); $link2->save(); - $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class); $this->layoutCacheKeyMock->expects($this->any()) ->method('getCacheKeys') ->willReturn([]); diff --git a/lib/internal/Magento/Framework/View/Model/Layout/CacheKey.php b/lib/internal/Magento/Framework/View/Model/Layout/CacheKey.php index e8a4ec1b405de..353eb3f46a540 100644 --- a/lib/internal/Magento/Framework/View/Model/Layout/CacheKey.php +++ b/lib/internal/Magento/Framework/View/Model/Layout/CacheKey.php @@ -36,7 +36,8 @@ public function addCacheKeys($cacheKeys) * * @return array */ - public function getCacheKeys() { + public function getCacheKeys() + { return $this->cacheKeys; } } 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 36841d2a74d50..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 { @@ -43,7 +44,7 @@ class MergeTest extends \PHPUnit\Framework\TestCase private $appState; /** - * @var \Magento\Framework\View\Layout\LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LayoutCacheKeyInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $layoutCacheKeyMock; @@ -60,7 +61,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->layoutCacheKeyMock = $this->getMockForAbstractClass(\Magento\Framework\View\Layout\LayoutCacheKeyInterface::class); + $this->layoutCacheKeyMock = $this->getMockForAbstractClass(LayoutCacheKeyInterface::class); $this->layoutCacheKeyMock->expects($this->any()) ->method('getCacheKeys') ->willReturn([]); From efa3edbc87c01316ea7b360b74d9a161991432af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 22 Sep 2017 14:35:18 +0200 Subject: [PATCH 13/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Adapted PageCache and Framework tests --- lib/internal/Magento/Framework/View/Model/Layout/Merge.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php index e08ae3e89f6ea..b804750d5e55f 100644 --- a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php +++ b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php @@ -727,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); @@ -926,6 +926,7 @@ public function getScope() */ public function getCacheId() { - return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $this->layoutCacheKey->getCacheKeys())))); + return $this->generateCacheId(md5(implode('|', + array_merge($this->getHandles(), $this->layoutCacheKey->getCacheKeys())))); } } From 3f60168240b43780b25940e01780e1771d29b366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 22 Sep 2017 15:18:41 +0200 Subject: [PATCH 14/14] Fix PageCache: async rendering of blocks can corrupt layout cache #8554 #9050 #9560 Adapted PageCache and Framework tests --- lib/internal/Magento/Framework/View/Model/Layout/Merge.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php index b804750d5e55f..ea8f74107954c 100644 --- a/lib/internal/Magento/Framework/View/Model/Layout/Merge.php +++ b/lib/internal/Magento/Framework/View/Model/Layout/Merge.php @@ -926,7 +926,7 @@ public function getScope() */ public function getCacheId() { - return $this->generateCacheId(md5(implode('|', - array_merge($this->getHandles(), $this->layoutCacheKey->getCacheKeys())))); + $layoutCacheKeys = $this->layoutCacheKey->getCacheKeys(); + return $this->generateCacheId(md5(implode('|', array_merge($this->getHandles(), $layoutCacheKeys)))); } }