Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensured the Page cache identifier is read in the same way and checking and saving the cache identifier #38646

Open
wants to merge 9 commits into
base: 2.4-develop
Choose a base branch
from
Open
61 changes: 61 additions & 0 deletions app/code/Magento/PageCache/Model/App/Request/Http/Identifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);

namespace Magento\PageCache\Model\App\Request\Http;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\PageCache\IdentifierInterface;
use Magento\Framework\Serialize\Serializer\Json;

class Identifier implements IdentifierInterface
{
/**
* @var \Magento\Framework\App\Request\Http
*/
protected $request;

/**
* @var \Magento\Framework\App\Http\Context
*/
protected $context;

/**
* @var Json
*/
private $serializer;

/**
* @param \Magento\Framework\App\Request\Http $request
* @param \Magento\Framework\App\Http\Context $context
* @param Json|null $serializer
*/
public function __construct(
\Magento\Framework\App\Request\Http $request,
\Magento\Framework\App\Http\Context $context,
Json $serializer = null,
private IdentifierStoreReader $identifierStoreReader
) {
$this->request = $request;
$this->context = $context;
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
}

/**
* Return unique page identifier
*
* @return string
*/
public function getValue()
{
$data = [
$this->request->isSecure(),
$this->request->getUriString(),
$this->request->get(\Magento\Framework\App\Response\Http::COOKIE_VARY_STRING)
?: $this->context->getVaryString()
];

$data = $this->identifierStoreReader->getPageTagsWithStoreCacheTags($data);

return sha1($this->serializer->serialize($data));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ class IdentifierForSave implements IdentifierInterface
* @param Json $serializer
*/
public function __construct(
private Http $request,
private Context $context,
private Json $serializer
private Http $request,
private Context $context,
private Json $serializer,
private IdentifierStoreReader $identifierStoreReader,
) {
}

Expand All @@ -42,6 +43,8 @@ public function getValue()
$this->context->getVaryString()
];

$data = $this->identifierStoreReader->getPageTagsWithStoreCacheTags($data);

return sha1($this->serializer->serialize($data));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);

namespace Magento\PageCache\Model\App\Request\Http;

use Magento\Store\Model\StoreManager;

class IdentifierStoreReader
{
/**
* @var \Magento\Framework\View\DesignExceptions
*/
private $designExceptions;

/**
* @var \Magento\Framework\App\RequestInterface
*/
private $request;

/**
* @var \Magento\PageCache\Model\Config
*/
private $config;

/**
* @param \Magento\Framework\View\DesignExceptions $designExceptions
* @param \Magento\Framework\App\RequestInterface $request
* @param \Magento\PageCache\Model\Config $config
*/
public function __construct(
\Magento\Framework\View\DesignExceptions $designExceptions,
\Magento\Framework\App\RequestInterface $request,
\Magento\PageCache\Model\Config $config
) {
$this->designExceptions = $designExceptions;
$this->request = $request;
$this->config = $config;
}

/**
* Adds a theme key to identifier for a built-in cache if user-agent theme rule is actual
*
* @param \Magento\Framework\App\PageCache\Identifier $identifier
* @param string $result
* @return array
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getPageTagsWithStoreCacheTags($data): ?array
{
if ($this->config->getType() === \Magento\PageCache\Model\Config::BUILT_IN && $this->config->isEnabled()) {
$ruleDesignException = $this->designExceptions->getThemeByRequest($this->request);
if ($ruleDesignException !== false) {
$data['DESIGN'] = $ruleDesignException;
}

if ($runType = $this->request->getServerValue(StoreManager::PARAM_RUN_TYPE)) {
$data[StoreManager::PARAM_RUN_TYPE] = $runType;
}

if ($runCode = $this->request->getServerValue(StoreManager::PARAM_RUN_CODE)) {
$data[StoreManager::PARAM_RUN_CODE] = $runCode;
}
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Magento\Framework\App\Request\Http as HttpRequest;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\PageCache\Model\App\Request\Http\IdentifierForSave;
use Magento\PageCache\Model\App\Request\Http\IdentifierStoreReader;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -40,6 +41,10 @@ class IdentifierForSaveTest extends TestCase
* @var Json|MockObject
*/
private mixed $serializerMock;
/**
* @var IdentifierStoreReader|MockObject
*/
private $identifierStoreReader;

/**
* @inheritdoc
Expand All @@ -64,10 +69,16 @@ function ($value) {
}
);

$this->identifierStoreReader = $this->getMockBuilder(IdentifierStoreReader::class)
->onlyMethods(['getPageTagsWithStoreCacheTags'])
->disableOriginalConstructor()
->getMock();

$this->model = new IdentifierForSave(
$this->requestMock,
$this->contextMock,
$this->serializerMock
$this->serializerMock,
$this->identifierStoreReader
);
parent::setUp();
}
Expand All @@ -91,6 +102,12 @@ public function testGetValue(): void
->method('getVaryString')
->willReturn(self::VARY);

$this->identifierStoreReader->method('getPageTagsWithStoreCacheTags')->willReturnCallback(
function ($value) {
return $value;
}
);

$this->assertEquals(
sha1(
json_encode(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php
declare(strict_types=1);

namespace Magento\PageCache\Test\Unit\Model\App\Request\Http;

use Magento\Framework\App\Request\Http;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Framework\View\DesignExceptions;
use Magento\PageCache\Model\Config;
use Magento\Store\Model\StoreManager;
use PHPUnit\Framework\TestCase;

class IdentifierStoreReaderTest extends TestCase
{
/**
* @var DesignExceptions|\PHPUnit\Framework\MockObject\MockObject
*/
private $designExceptionsMock;
/**
* @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject
*/
private \PHPUnit\Framework\MockObject\MockObject|RequestInterface $requestMock;
/**
* @var Config|\PHPUnit\Framework\MockObject\MockObject
*/
private $configMock;
/**
* @var \Magento\PageCache\Model\App\Request\Http\IdentifierStoreReader
*/
private $model;

protected function setUp(): void
{
$this->objectManager = new ObjectManager($this);

$this->designExceptionsMock = $this->createPartialMock(
DesignExceptions::class,
['getThemeByRequest']
);

$this->requestMock = $this->createMock(Http::class);

$this->configMock = $this->getMockBuilder(Config::class)
->onlyMethods(['getType', 'isEnabled'])
//->addMethods(['getType', 'isEnabled'])
->disableOriginalConstructor()
->getMockForAbstractClass();

$this->model = new \Magento\PageCache\Model\App\Request\Http\IdentifierStoreReader(
$this->designExceptionsMock,
$this->requestMock,
$this->configMock
);
}

public function testGetPageTagsWithStoreCacheTagsWhenVarnishCacheIsEnabled()
{
$this->configMock->expects($this->any())
->method('getType')
->willReturn(\Magento\PageCache\Model\Config::VARNISH);

$this->requestMock->expects($this->never())->method('getServerValue');

$data = ['anything'];
$this->model->getPageTagsWithStoreCacheTags($data);
}

public function testGetPageTagsWithStoreCacheTagsWhenFPCIsDisabled()
{
$this->configMock->expects($this->any())
->method('isEnabled')
->willReturn(false);

$this->requestMock->expects($this->never())->method('getServerValue');

$data = ['anything'];
$this->model->getPageTagsWithStoreCacheTags($data);
}

public function testGetPageTagsWithStoreCacheTagsWhenStoreDataAreInContext()
{
$this->configMock->expects($this->any())
->method('isEnabled')
->willReturn(true);

$this->configMock->expects($this->any())
->method('getType')
->willReturn(\Magento\PageCache\Model\Config::BUILT_IN);

$defaultRequestMock = clone $this->requestMock;
$defaultRequestMock->expects($this->any())
->method('getServerValue')
->willReturnCallback(
function ($param) {
if ($param == StoreManager::PARAM_RUN_TYPE) {
return 'store';
}
if ($param == StoreManager::PARAM_RUN_CODE) {
return 'default';
}
}
);

$data = ['anything'];

$this->model = new \Magento\PageCache\Model\App\Request\Http\IdentifierStoreReader(
$this->designExceptionsMock,
$defaultRequestMock,
$this->configMock
);
$newData = $this->model->getPageTagsWithStoreCacheTags($data);

$this->assertArrayHasKey(StoreManager::PARAM_RUN_TYPE, $newData);
$this->assertArrayHasKey(StoreManager::PARAM_RUN_CODE, $newData);
$this->assertEquals($newData[StoreManager::PARAM_RUN_TYPE], 'store');
$this->assertEquals($newData[StoreManager::PARAM_RUN_CODE], 'default');
}
}