mirror of
https://github.com/werkraum-media/events.git
synced 2024-11-21 16:56:11 +01:00
Respect new upcoming feature when calculating TTL of page cache (#17)
Relates: #10506
This commit is contained in:
parent
99ef32a37b
commit
76c1e79ea3
6 changed files with 141 additions and 23 deletions
|
@ -25,10 +25,12 @@ namespace Wrm\Events\Caching;
|
|||
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use InvalidArgumentException;
|
||||
use TYPO3\CMS\Core\Cache\CacheManager;
|
||||
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
use Wrm\Events\Domain\Model\Date;
|
||||
use Wrm\Events\Events\Controller\DateListVariables;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +44,7 @@ class PageCacheTimeout implements SingletonInterface
|
|||
/**
|
||||
* @var null|DateTimeImmutable
|
||||
*/
|
||||
private $endOfEvent = null;
|
||||
private $timeout = null;
|
||||
|
||||
/**
|
||||
* @var FrontendInterface
|
||||
|
@ -78,46 +80,74 @@ class PageCacheTimeout implements SingletonInterface
|
|||
public function trackDates(DateListVariables $event): void
|
||||
{
|
||||
if ($event->getDemand()->shouldShowFromMidnight()) {
|
||||
$this->updateTimeout((new DateTimeImmutable('tomorrow midnight')));
|
||||
$this->updateTimeout(new DateTimeImmutable('tomorrow midnight'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->getDemand()->shouldShowUpcoming()) {
|
||||
$this->trackTimeoutByDate($event, static function (Date $date) {
|
||||
return $date->getStart();
|
||||
});
|
||||
}
|
||||
|
||||
$this->trackTimeoutByDate($event, static function (Date $date) {
|
||||
return $date->getEnd();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callback Receives Date as argument and should return DateTime to use as potential timeout.
|
||||
*/
|
||||
private function trackTimeoutByDate(
|
||||
DateListVariables $event,
|
||||
callable $callback
|
||||
): void {
|
||||
foreach ($event->getDates() as $date) {
|
||||
$endDate = $date->getEnd();
|
||||
if (!$endDate instanceof DateTime) {
|
||||
$date = $callback($date);
|
||||
if (!$date instanceof DateTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->updateTimeout(DateTimeImmutable::createFromMutable($endDate));
|
||||
$this->updateTimeout(DateTimeImmutable::createFromMutable($date));
|
||||
}
|
||||
}
|
||||
|
||||
private function updateTimeout(DateTimeImmutable $end): void
|
||||
private function updateTimeout(DateTimeImmutable $newTimeout): void
|
||||
{
|
||||
$now = new DateTimeImmutable();
|
||||
$now = $this->getExecution();
|
||||
|
||||
if (
|
||||
$end <= $now
|
||||
$newTimeout <= $now
|
||||
|| (
|
||||
$this->endOfEvent instanceof DateTimeImmutable
|
||||
&& $this->endOfEvent >= $end
|
||||
$this->timeout instanceof DateTimeImmutable
|
||||
&& $this->timeout >= $newTimeout
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->runtimeCache->remove('core-tslib_fe-get_cache_timeout');
|
||||
$this->endOfEvent = $end;
|
||||
$this->timeout = $newTimeout;
|
||||
}
|
||||
|
||||
private function getTimeout(): ?int
|
||||
{
|
||||
if (!$this->endOfEvent instanceof DateTimeImmutable) {
|
||||
if (!$this->timeout instanceof DateTimeImmutable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$executionTime = $this->context->getPropertyFromAspect('date', 'timestamp');
|
||||
return ((int) $this->endOfEvent->format('U')) - $executionTime;
|
||||
return ((int) $this->timeout->format('U')) - ((int) $this->getExecution()->format('U'));
|
||||
}
|
||||
|
||||
private function getExecution(): DateTimeImmutable
|
||||
{
|
||||
$execution = $this->context->getPropertyFromAspect('date', 'full');
|
||||
|
||||
if (!$execution instanceof DateTimeImmutable) {
|
||||
throw new InvalidArgumentException('Could not fetch DateTimeImmutable from context.', 1684740576);
|
||||
}
|
||||
|
||||
return $execution;
|
||||
}
|
||||
|
||||
public static function register(): void
|
||||
|
|
|
@ -10,8 +10,15 @@ Features
|
|||
--------
|
||||
|
||||
* Adjust TYPO3 page cache timeout based on rendered dates.
|
||||
The end time of each rendered date will be used.
|
||||
The lowest end date will be used to calculate the maximum time to life for the page cache.
|
||||
Will use one of the following:
|
||||
|
||||
- end time of each rendered date
|
||||
|
||||
- start time of each rendered date (if upcoming is enabled)
|
||||
|
||||
- midnight (if midnight is configured)
|
||||
|
||||
The lowest date will be used to calculate the maximum time to life for the page cache.
|
||||
This is compared to the already calculated time to life.
|
||||
The lower value is then used by TYPO3.
|
||||
|
||||
|
|
13
Documentation/Features.rst
Normal file
13
Documentation/Features.rst
Normal file
|
@ -0,0 +1,13 @@
|
|||
.. _features:
|
||||
|
||||
Features
|
||||
=========
|
||||
|
||||
The extension provides a couple of features.
|
||||
The following is an incomplete list of the feature set with further info per feature.
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
Features/*
|
28
Documentation/Features/Caching.rst
Normal file
28
Documentation/Features/Caching.rst
Normal file
|
@ -0,0 +1,28 @@
|
|||
.. _caching:
|
||||
|
||||
.. index:: single: caching
|
||||
|
||||
Caching
|
||||
=======
|
||||
|
||||
The extension provides out of the box support for proper TYPO3 page caching.
|
||||
|
||||
Page Cache
|
||||
----------
|
||||
|
||||
TYPO3 can cache the full page with a TTL (=time to live).
|
||||
The TTL can be adjusted via configuration and code.
|
||||
The extension uses the code to lower TTL if necessary.
|
||||
|
||||
The TTL of the extension is determined in the following way:
|
||||
|
||||
#. Upcoming midnight if midnight should be used.
|
||||
|
||||
#. Start of each shown date if upcoming should be used.
|
||||
|
||||
#. End of each shown date as fallback.
|
||||
|
||||
The corresponding code is ``Wrm\Events\Caching\PageCacheTimeout``.
|
||||
|
||||
That way the TTL of each page is not longer than the valid period for shown events,
|
||||
leading to re-rendering of the page once an event might change.
|
|
@ -42,6 +42,7 @@ Table of Contents
|
|||
:maxdepth: 3
|
||||
:titlesonly:
|
||||
|
||||
Features
|
||||
Commands
|
||||
Settings
|
||||
Changelog
|
||||
|
|
|
@ -67,7 +67,7 @@ class CacheTest extends AbstractTestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setupReturnsSystemDefaults(): void
|
||||
public function returnsSystemDefaults(): void
|
||||
{
|
||||
$response = $this->executeFrontendRequest($this->getRequestWithSleep());
|
||||
|
||||
|
@ -79,7 +79,7 @@ class CacheTest extends AbstractTestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setupReturnsDefaultsIfEventsEndLater(): void
|
||||
public function returnsDefaultsIfEventsEndLater(): void
|
||||
{
|
||||
(new PhpDataSet())->import([
|
||||
'tx_events_domain_model_event' => [
|
||||
|
@ -107,7 +107,7 @@ class CacheTest extends AbstractTestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setupReturnsEarlierIfEventsChangeBeforeSystemDefault(): void
|
||||
public function returnsEarlierIfEventsEndEarlier(): void
|
||||
{
|
||||
$end = (new DateTimeImmutable('tomorrow midnight', new DateTimeZone('UTC')))->modify('+2 hours');
|
||||
|
||||
|
@ -138,7 +138,46 @@ class CacheTest extends AbstractTestCase
|
|||
/**
|
||||
* @test
|
||||
*/
|
||||
public function setupReturnsMidnightIfConfigured(): void
|
||||
public function returnsEarlierIfStartEndEalierAndIsUpcoming(): void
|
||||
{
|
||||
$end = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->modify('+2 hours');
|
||||
|
||||
(new PhpDataSet())->import([
|
||||
'tx_events_domain_model_event' => [
|
||||
[
|
||||
'uid' => '1',
|
||||
'pid' => '2',
|
||||
'title' => 'Test Event 1',
|
||||
],
|
||||
],
|
||||
'tx_events_domain_model_date' => [
|
||||
[
|
||||
'pid' => '2',
|
||||
'event' => '1',
|
||||
'start' => $end->format('U'),
|
||||
'end' => '0',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$response = $this->executeFrontendRequest($this->getRequestWithSleep([
|
||||
'plugin.' => [
|
||||
'tx_events.' => [
|
||||
'settings.' => [
|
||||
'upcoming' => 1,
|
||||
],
|
||||
],
|
||||
],
|
||||
]));
|
||||
|
||||
self::assertSame(200, $response->getStatusCode());
|
||||
self::assertCacheHeaders($end, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsMidnightIfConfigured(): void
|
||||
{
|
||||
$midnight = (new DateTimeImmutable('tomorrow midnight', new DateTimeZone('UTC')));
|
||||
|
||||
|
@ -207,13 +246,13 @@ class CacheTest extends AbstractTestCase
|
|||
];
|
||||
}
|
||||
|
||||
private function getRequestWithSleep(): InternalRequest
|
||||
private function getRequestWithSleep(array $typoScript = []): InternalRequest
|
||||
{
|
||||
$request = new InternalRequest();
|
||||
$request = $request->withPageId(1);
|
||||
$request = $request->withInstructions([
|
||||
$this->getTypoScriptInstruction()
|
||||
->withTypoScript([
|
||||
->withTypoScript(array_merge_recursive($typoScript, [
|
||||
'page.' => [
|
||||
'30.' => [
|
||||
'userFunc.' => [
|
||||
|
@ -221,7 +260,7 @@ class CacheTest extends AbstractTestCase
|
|||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
]))
|
||||
]);
|
||||
|
||||
return $request;
|
||||
|
|
Loading…
Reference in a new issue