|
<?php |
|
|
|
namespace Drupal\mymodule\StackMiddleware; |
|
|
|
use Drupal\Core\Cache\CacheTagsInvalidator; |
|
use Drupal\Core\Datetime\DateFormatter; |
|
use Drupal\Core\State\State; |
|
use Symfony\Component\HttpFoundation\Request; |
|
use Symfony\Component\HttpKernel\HttpKernelInterface; |
|
|
|
/** |
|
* Provides and invalidates cache tags for hourly / daily changes. |
|
* |
|
* Example: |
|
* Blocks needing a refresh every full hour should be tagged using |
|
* the cache tag defined in constant CacheTimeout::HOURLY. |
|
*/ |
|
class CacheTimeout implements HttpKernelInterface { |
|
|
|
// Some constants to use elsewhere. |
|
public const HOURLY = 'mymodule:hourly'; |
|
public const DAILY = 'mymodule:daily'; |
|
public const STATE = 'mymodule.last_invalidated'; |
|
|
|
/** |
|
* The wrapped HTTP kernel. |
|
* |
|
* @var \Symfony\Component\HttpKernel\HttpKernelInterface |
|
*/ |
|
protected HttpKernelInterface $httpKernel; |
|
|
|
/** |
|
* The date formatter. |
|
* |
|
* @var \Drupal\Core\Datetime\DateFormatter |
|
*/ |
|
protected DateFormatter $dateFormatter; |
|
|
|
/** |
|
* The state service. |
|
* |
|
* @var \Drupal\Core\State\State |
|
*/ |
|
protected State $state; |
|
|
|
/** |
|
* The cache tags invalidator. |
|
* |
|
* @var \Drupal\Core\Cache\CacheTagsInvalidator |
|
*/ |
|
protected CacheTagsInvalidator $cacheTagsInvalidator; |
|
|
|
/** |
|
* Constructs a new CacheTimeout instance. |
|
* |
|
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel |
|
* The wrapped HTTP kernel. |
|
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter |
|
* The date formatter. |
|
* @param \Drupal\Core\State\State $state |
|
* The state service. |
|
* @param \Drupal\Core\Cache\CacheTagsInvalidator $cache_tags_invalidator |
|
* The cache tags invalidator. |
|
*/ |
|
public function __construct(HttpKernelInterface $http_kernel, DateFormatter $date_formatter, State $state, CacheTagsInvalidator $cache_tags_invalidator) { |
|
$this->httpKernel = $http_kernel; |
|
$this->dateFormatter = $date_formatter; |
|
$this->state = $state; |
|
$this->cacheTagsInvalidator = $cache_tags_invalidator; |
|
} |
|
|
|
/** |
|
* {@inheritdoc} |
|
*/ |
|
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { |
|
|
|
// We're taking care of master requests only. |
|
if ($type !== self::MASTER_REQUEST) { |
|
return $this->httpKernel->handle($request, $type, $catch); |
|
} |
|
|
|
// Get the state variable indicating the last invalidation (YYYYMMDDHH) |
|
$last_invalidation = $this->state->get(self::STATE, '0000000000'); |
|
|
|
// Get the current request time. |
|
$current_time = $this->dateFormatter->format( |
|
time(), 'custom', 'YmdH', 'Europe/Berlin' |
|
); |
|
|
|
// Handle daily invalidation (implies hourly invalidation, too). |
|
if (strncmp($last_invalidation, $current_time, 8) < 0) { |
|
$this->cacheTagsInvalidator->invalidateTags([ |
|
self::DAILY, |
|
self::HOURLY, |
|
]); |
|
$this->state->set(self::STATE, $current_time); |
|
return $this->httpKernel->handle($request, $type, $catch); |
|
} |
|
|
|
// Handle hourly invalidation. |
|
if ($last_invalidation < $current_time) { |
|
$this->cacheTagsInvalidator->invalidateTags([self::HOURLY]); |
|
$this->state->set(self::STATE, $current_time); |
|
return $this->httpKernel->handle($request, $type, $catch); |
|
} |
|
|
|
// No need to invalidate cache tags. |
|
return $this->httpKernel->handle($request, $type, $catch); |
|
} |
|
|
|
} |