diff --git a/extend.php b/extend.php index 58b1a6e..27335f0 100644 --- a/extend.php +++ b/extend.php @@ -34,10 +34,11 @@ // Settings (new Extend\Settings()) + ->default('acpl-lscache.cache_enabled', true) ->default('acpl-lscache.public_cache_ttl', 604_800) ->default('acpl-lscache.clearing_cache_listener', true) ->default('acpl-lscache.drop_qs', implode("\n", LSCache::DEFAULT_DROP_QS)), - (new Extend\Event())->listen(Saved::class, Listener\UpdateHtaccess::class), + (new Extend\Event())->listen(Saved::class, Listener\UpdateSettings::class), // Vary cookie (new Extend\Middleware('forum'))->insertAfter(StartSession::class, VaryCookieMiddleware::class), diff --git a/js/src/admin/index.tsx b/js/src/admin/index.tsx index e50cd39..ad3b2f1 100644 --- a/js/src/admin/index.tsx +++ b/js/src/admin/index.tsx @@ -5,6 +5,20 @@ import addPurgeLSCacheButton from './addPurgeLSCacheButton'; app.initializers.add('acpl-lscache', () => { app.extensionData .for('acpl-lscache') + .registerSetting({ + setting: 'acpl-lscache.cache_enabled', + label: app.translator.trans('acpl-lscache.admin.cache_enabled_label'), + help: app.translator.trans('acpl-lscache.admin.cache_enabled_help', { + a: ( + + ), + }), + type: 'boolean', + }) .registerSetting({ setting: 'acpl-lscache.public_cache_ttl', label: app.translator.trans('acpl-lscache.admin.public_cache_ttl_label'), diff --git a/locale/en.yml b/locale/en.yml index 6a81b78..7760c5f 100644 --- a/locale/en.yml +++ b/locale/en.yml @@ -1,5 +1,8 @@ acpl-lscache: admin: + cache_enabled_label: "Enable LSCache" + cache_enabled_help: "Check out the Information page on how to test the cache. NOTE: When disabling the cache, all cached entries for this site will be purged." + public_cache_ttl_label: "Default Public Cache TTL" public_cache_ttl_help: "Define how long, in seconds, public pages should be cached. The default value is 604800 seconds (one week)." diff --git a/src/Listener/UpdateHtaccess.php b/src/Listener/UpdateHtaccess.php deleted file mode 100644 index 5656e6f..0000000 --- a/src/Listener/UpdateHtaccess.php +++ /dev/null @@ -1,27 +0,0 @@ -htaccessManager = $htaccessManager; - } - - /** - * @throws FileNotFoundException - */ - public function handle(Saved $event): void - { - if (isset($event->settings['acpl-lscache.drop_qs'])) { - $this->htaccessManager->updateHtaccess(); - } - } -} diff --git a/src/Listener/UpdateSettings.php b/src/Listener/UpdateSettings.php new file mode 100644 index 0000000..ff02276 --- /dev/null +++ b/src/Listener/UpdateSettings.php @@ -0,0 +1,38 @@ +htaccessManager = $htaccessManager; + $this->cacheClearCommand = $command; + } + + /** + * @throws FileNotFoundException|ExceptionInterface + */ + public function handle(Saved $event): void + { + if (isset($event->settings['acpl-lscache.drop_qs'])) { + $this->htaccessManager->updateHtaccess(); + } + + // If the LSCache is being disabled, initiate a cache clear operation. + if (isset($event->settings['acpl-lscache.cache_enabled']) && $event->settings['acpl-lscache.cache_enabled'] === false) { + $this->cacheClearCommand->run(new ArrayInput([]), new NullOutput()); + } + } +} diff --git a/src/Middleware/LSCacheControlMiddleware.php b/src/Middleware/LSCacheControlMiddleware.php index 2be7355..987aff4 100644 --- a/src/Middleware/LSCacheControlMiddleware.php +++ b/src/Middleware/LSCacheControlMiddleware.php @@ -28,6 +28,10 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $handler->handle($request); $method = $request->getMethod(); + if ($this->settings->get('acpl-lscache.cache_enabled', true) === false) { + return $this->withCacheControlHeader($response, 'no-cache'); + } + if (! in_array($method, ['GET', 'HEAD']) || $response->hasHeader(LSCacheHeadersEnum::CACHE_CONTROL)) { return $response; } @@ -58,9 +62,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface //Cache CSRF privately if ($routeName === 'lscache.csrf') { - $sessionTTL = $this->session['lifetime'] * 60; - - return $this->withCacheControlHeader($response, "private,max-age=$sessionTTL"); + // Subtract 2 minutes (120 seconds) + // from the session lifetime to set the cache to expire before the actual session does. + // This is to prevent a potential issue where an expired CSRF token might be served from the cache. + return $this->withCacheControlHeader( + $response, + 'private,max-age='.(($this->session['lifetime'] * 60) - 120) + ); } $lscacheParams = [];