From 4e4ef56bb21700c0a2105e0f4208a560ae3ad8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:22:42 +0200 Subject: [PATCH 01/38] chore: bump a minimum PHP version to 8.1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bd946b8..5645531 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ ], "require": { "flarum/core": "^1.8", - "php": ">=8.0" + "php": ">=8.1" }, "require-dev": { "flarum/phpstan": "^1.8", From e115694ed653aa711ff3f4289196c38c7b680f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:05:03 +0200 Subject: [PATCH 02/38] feat: use events to purge LSCache --- extend.php | 75 ++++++------- src/Api/Controller/PurgeLSCacheController.php | 4 +- ...arumLikesAbstractPurgeCacheMiddleware.php} | 6 +- ...larumTagsAbstractPurgeCacheMiddleware.php} | 6 +- ...asqueradeAbstractPurgeCacheMiddleware.php} | 8 +- ...larumBlogAbstractPurgeCacheMiddleware.php} | 12 +-- src/LSCache.php | 4 +- ...CacheHeadersEnum.php => LSCacheHeader.php} | 2 +- src/Listener/AbstractCachePurgeListener.php | 19 ++++ src/Listener/AbstractCachePurgeSubscriber.php | 21 ++++ src/Listener/ClearingCacheListener.php | 23 ++-- src/Listener/DiscussionEventSubscriber.php | 43 ++++++++ src/Listener/UpdateSettings.php | 38 ------- src/Listener/UpdateSettingsListener.php | 29 +++++ .../AbstractCacheTagsMiddleware.php} | 16 +-- .../AbstractPurgeCacheMiddleware.php} | 37 +++---- ...dleware.php => CacheControlMiddleware.php} | 23 ++-- src/Middleware/LSCachePurgeMiddleware.php | 100 ------------------ ...eware.php => LSTagsMiddlewareAbstract.php} | 5 +- src/Middleware/LoginMiddleware.php | 6 +- src/Middleware/LogoutMiddleware.php | 13 +-- src/Middleware/PurgeCacheMiddleware.php | 51 +++++++++ src/Middleware/VaryCookieMiddleware.php | 10 +- 23 files changed, 273 insertions(+), 278 deletions(-) rename src/Compatibility/Flarum/Likes/{FlarumLikesPurgeMiddleware.php => FlarumLikesAbstractPurgeCacheMiddleware.php} (79%) rename src/Compatibility/Flarum/Tags/{FlarumTagsPurgeMiddleware.php => FlarumTagsAbstractPurgeCacheMiddleware.php} (93%) rename src/Compatibility/FriendsOfFlarum/Masquerade/{FofMasqueradePurgeMiddleware.php => FofMasqueradeAbstractPurgeCacheMiddleware.php} (83%) rename src/Compatibility/v17development/FlarumBlog/{FlarumBlogPurgeMiddleware.php => FlarumBlogAbstractPurgeCacheMiddleware.php} (89%) rename src/{LSCacheHeadersEnum.php => LSCacheHeader.php} (86%) create mode 100644 src/Listener/AbstractCachePurgeListener.php create mode 100644 src/Listener/AbstractCachePurgeSubscriber.php create mode 100644 src/Listener/DiscussionEventSubscriber.php delete mode 100644 src/Listener/UpdateSettings.php create mode 100644 src/Listener/UpdateSettingsListener.php rename src/{Abstract/CacheTagsMiddleware.php => Middleware/AbstractCacheTagsMiddleware.php} (74%) rename src/{Abstract/PurgeMiddleware.php => Middleware/AbstractPurgeCacheMiddleware.php} (60%) rename src/Middleware/{LSCacheControlMiddleware.php => CacheControlMiddleware.php} (84%) delete mode 100644 src/Middleware/LSCachePurgeMiddleware.php rename src/Middleware/{LSTagsMiddleware.php => LSTagsMiddlewareAbstract.php} (90%) create mode 100644 src/Middleware/PurgeCacheMiddleware.php diff --git a/extend.php b/extend.php index 8519688..2219005 100644 --- a/extend.php +++ b/extend.php @@ -14,16 +14,17 @@ use ACPL\FlarumCache\Api\Controller\LSCacheCsrfResponseController; use ACPL\FlarumCache\Api\Controller\PurgeLSCacheController; use ACPL\FlarumCache\Command\LSCacheClearCommand; -use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesPurgeMiddleware; -use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsPurgeMiddleware; -use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradePurgeMiddleware; -use ACPL\FlarumCache\Compatibility\v17development\FlarumBlog\FlarumBlogPurgeMiddleware; +use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesAbstractPurgeCacheMiddleware; +use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsAbstractPurgeCacheMiddleware; +use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradeAbstractPurgeCacheMiddleware; +use ACPL\FlarumCache\Compatibility\v17development\FlarumBlog\FlarumBlogAbstractPurgeCacheMiddleware; use ACPL\FlarumCache\Listener\ClearingCacheListener; +use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; +use ACPL\FlarumCache\Middleware\CacheControlMiddleware; use ACPL\FlarumCache\Middleware\LoginMiddleware; use ACPL\FlarumCache\Middleware\LogoutMiddleware; -use ACPL\FlarumCache\Middleware\LSCacheControlMiddleware; -use ACPL\FlarumCache\Middleware\LSCachePurgeMiddleware; -use ACPL\FlarumCache\Middleware\LSTagsMiddleware; +use ACPL\FlarumCache\Middleware\LSTagsMiddlewareAbstract; +use ACPL\FlarumCache\Middleware\PurgeCacheMiddleware; use ACPL\FlarumCache\Middleware\VaryCookieMiddleware; use Flarum\Extend; use Flarum\Foundation\Event\ClearingCache; @@ -41,7 +42,7 @@ ->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\UpdateSettings::class), + (new Extend\Event())->listen(Saved::class, Listener\UpdateSettingsListener::class), // Vary cookie (new Extend\Middleware('forum'))->insertAfter(CheckCsrfToken::class, VaryCookieMiddleware::class), @@ -53,43 +54,45 @@ (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, LogoutMiddleware::class), // Tag routes - (new Extend\Middleware('forum'))->add(LSTagsMiddleware::class), - (new Extend\Middleware('api'))->add(LSTagsMiddleware::class), + (new Extend\Middleware('forum'))->add(LSTagsMiddlewareAbstract::class), + (new Extend\Middleware('api'))->add(LSTagsMiddlewareAbstract::class), // Cache routes - (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, LSCacheControlMiddleware::class), - (new Extend\Middleware('api'))->insertAfter(VaryCookieMiddleware::class, LSCacheControlMiddleware::class), + (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, CacheControlMiddleware::class), + (new Extend\Middleware('api'))->insertAfter(VaryCookieMiddleware::class, CacheControlMiddleware::class), // A workaround for the CSRF cache issue. The JS script fetches this path to update the CSRF (new Extend\Routes('api'))->get('/lscache-csrf', 'lscache.csrf', LSCacheCsrfResponseController::class), // Purge cache on update - (new Extend\Middleware('forum'))->add(LSCachePurgeMiddleware::class), - (new Extend\Middleware('admin'))->add(LSCachePurgeMiddleware::class), - (new Extend\Middleware('api'))->add(LSCachePurgeMiddleware::class), + (new Extend\Middleware('forum'))->add(PurgeCacheMiddleware::class), + (new Extend\Middleware('admin'))->add(PurgeCacheMiddleware::class), + (new Extend\Middleware('api'))->add(PurgeCacheMiddleware::class), // Purge cache (new Extend\Routes('api'))->get('/lscache-purge', 'lscache.purge', PurgeLSCacheController::class), - (new Extend\Console())->command(LSCacheClearCommand::class), - (new Extend\Event())->listen(ClearingCache::class, ClearingCacheListener::class), + (new Extend\Console)->command(LSCacheClearCommand::class), + (new Extend\Event)->listen(ClearingCache::class, ClearingCacheListener::class), - // Compatibility with extensions - (new Extend\Conditional) - ->whenExtensionEnabled('flarum-tags', [ - (new Extend\Middleware('api'))->add(FlarumTagsPurgeMiddleware::class), - ]) - ->whenExtensionEnabled('flarum-likes', [ - (new Extend\Middleware('api'))->add(FlarumLikesPurgeMiddleware::class), - ]) - ->whenExtensionEnabled('fof-masquerade', [ - (new Extend\Middleware('api'))->add(FofMasqueradePurgeMiddleware::class), - ]) - ->whenExtensionEnabled('v17development-blog', [ - // Using insertBefore enables reading headers set by LSCachePurgeMiddleware, while insertAfter does not. - // This suggests Flarum processes middleware in a reverse order 🤔. - (new Extend\Middleware('api'))->insertBefore( - LSCachePurgeMiddleware::class, - FlarumBlogPurgeMiddleware::class - ), - ]) + (new Extend\Event)->subscribe(DiscussionEventSubscriber::class), + + /*// Compatibility with extensions + (new Extend\Conditional) + ->whenExtensionEnabled('flarum-tags', [ + (new Extend\Middleware('api'))->add(FlarumTagsAbstractPurgeCacheMiddleware::class), + ]) + ->whenExtensionEnabled('flarum-likes', [ + (new Extend\Middleware('api'))->add(FlarumLikesAbstractPurgeCacheMiddleware::class), + ]) + ->whenExtensionEnabled('fof-masquerade', [ + (new Extend\Middleware('api'))->add(FofMasqueradeAbstractPurgeCacheMiddleware::class), + ]) + ->whenExtensionEnabled('v17development-blog', [ + // Using insertBefore enables reading headers set by LSCachePurgeMiddleware, while insertAfter does not. + // This suggests Flarum processes middleware in a reverse order 🤔. + (new Extend\Middleware('api'))->insertBefore( + PurgeCacheMiddleware::class, + FlarumBlogAbstractPurgeCacheMiddleware::class, + ), + ]),*/ ]; diff --git a/src/Api/Controller/PurgeLSCacheController.php b/src/Api/Controller/PurgeLSCacheController.php index fef0d4a..2ac7423 100644 --- a/src/Api/Controller/PurgeLSCacheController.php +++ b/src/Api/Controller/PurgeLSCacheController.php @@ -2,7 +2,7 @@ namespace ACPL\FlarumCache\Api\Controller; -use ACPL\FlarumCache\LSCacheHeadersEnum; +use ACPL\FlarumCache\LSCacheHeader; use Flarum\Http\RequestUtil; use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\Exception\PermissionDeniedException; @@ -54,6 +54,6 @@ public function handle(ServerRequestInterface $request): ResponseInterface $purgeStr .= '*'; } - return (new EmptyResponse())->withHeader(LSCacheHeadersEnum::PURGE, $purgeStr); + return (new EmptyResponse())->withHeader(LSCacheHeader::PURGE, $purgeStr); } } diff --git a/src/Compatibility/Flarum/Likes/FlarumLikesPurgeMiddleware.php b/src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php similarity index 79% rename from src/Compatibility/Flarum/Likes/FlarumLikesPurgeMiddleware.php rename to src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php index 4e7383f..8dbd63b 100644 --- a/src/Compatibility/Flarum/Likes/FlarumLikesPurgeMiddleware.php +++ b/src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php @@ -2,18 +2,18 @@ namespace ACPL\FlarumCache\Compatibility\Flarum\Likes; -use ACPL\FlarumCache\Abstract\PurgeMiddleware; +use ACPL\FlarumCache\Middleware\AbstractPurgeCacheMiddleware; use Illuminate\Support\Arr; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -class FlarumLikesPurgeMiddleware extends PurgeMiddleware +class FlarumLikesAbstractPurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { protected function processPurge( ServerRequestInterface $request, RequestHandlerInterface $handler, - ResponseInterface $response + ResponseInterface $response, ): ResponseInterface { if ($this->currentRouteName !== 'posts.update') { return $response; diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsPurgeMiddleware.php b/src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php similarity index 93% rename from src/Compatibility/Flarum/Tags/FlarumTagsPurgeMiddleware.php rename to src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php index 90c0d59..c4a4a7a 100644 --- a/src/Compatibility/Flarum/Tags/FlarumTagsPurgeMiddleware.php +++ b/src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php @@ -2,7 +2,7 @@ namespace ACPL\FlarumCache\Compatibility\Flarum\Tags; -use ACPL\FlarumCache\Abstract\PurgeMiddleware; +use ACPL\FlarumCache\Middleware\AbstractPurgeCacheMiddleware; use Flarum\Discussion\Discussion; use Flarum\Http\UrlGenerator; use Flarum\Post\Post; @@ -13,7 +13,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -class FlarumTagsPurgeMiddleware extends PurgeMiddleware +class FlarumTagsAbstractPurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { protected UrlGenerator $url; @@ -26,7 +26,7 @@ public function __construct(SettingsRepositoryInterface $settings, UrlGenerator protected function processPurge( ServerRequestInterface $request, RequestHandlerInterface $handler, - ResponseInterface $response + ResponseInterface $response, ): ResponseInterface { $isDiscussion = $this->isDiscussion; $isPost = $this->isPost; diff --git a/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeMiddleware.php b/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradeAbstractPurgeCacheMiddleware.php similarity index 83% rename from src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeMiddleware.php rename to src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradeAbstractPurgeCacheMiddleware.php index 24dc74a..3cd22e0 100644 --- a/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeMiddleware.php +++ b/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradeAbstractPurgeCacheMiddleware.php @@ -2,18 +2,18 @@ namespace ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade; -use ACPL\FlarumCache\Abstract\PurgeMiddleware; +use ACPL\FlarumCache\Middleware\AbstractPurgeCacheMiddleware; use Flarum\User\User; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -class FofMasqueradePurgeMiddleware extends PurgeMiddleware +class FofMasqueradeAbstractPurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { protected function processPurge( ServerRequestInterface $request, RequestHandlerInterface $handler, - ResponseInterface $response + ResponseInterface $response, ): ResponseInterface { // Purge user profile cache when updating FriendsOfFlarum/masquerade fields if ($this->currentRouteName === 'masquerade.api.configure.save') { @@ -28,7 +28,7 @@ protected function processPurge( "tag=user_$user->username", "tag=users_$user->username", "tag=masquerade_$user->id", - ] + ], ); } diff --git a/src/Compatibility/v17development/FlarumBlog/FlarumBlogPurgeMiddleware.php b/src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php similarity index 89% rename from src/Compatibility/v17development/FlarumBlog/FlarumBlogPurgeMiddleware.php rename to src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php index f330cb0..7ce8d12 100644 --- a/src/Compatibility/v17development/FlarumBlog/FlarumBlogPurgeMiddleware.php +++ b/src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php @@ -2,8 +2,8 @@ namespace ACPL\FlarumCache\Compatibility\v17development\FlarumBlog; -use ACPL\FlarumCache\Abstract\PurgeMiddleware; -use ACPL\FlarumCache\LSCacheHeadersEnum; +use ACPL\FlarumCache\LSCacheHeader; +use ACPL\FlarumCache\Middleware\AbstractPurgeCacheMiddleware; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Psr\Http\Message\ResponseInterface; @@ -11,12 +11,12 @@ use Psr\Http\Server\RequestHandlerInterface; use V17Development\FlarumBlog\BlogMeta\BlogMeta; -class FlarumBlogPurgeMiddleware extends PurgeMiddleware +class FlarumBlogAbstractPurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { protected function processPurge( ServerRequestInterface $request, RequestHandlerInterface $handler, - ResponseInterface $response + ResponseInterface $response, ): ResponseInterface { $isDiscussion = $this->isDiscussion; $isPost = $this->isPost; @@ -32,7 +32,7 @@ protected function processPurge( } } - $currentPurgeParams = $response->getHeaderLine(LSCacheHeadersEnum::PURGE); + $currentPurgeParams = $response->getHeaderLine(LSCacheHeader::PURGE); if (empty($currentPurgeParams)) { return $response; } @@ -43,7 +43,7 @@ protected function processPurge( // Blog extension is using default Flarum discussion api routes, so we can just reuse previous middleware to get the blog post id $discussionParam = Arr::first( $currentPurgeParams, - fn (string $param) => Str::startsWith($param, ['tag=discussion_', 'tag=discussions_']) + fn (string $param) => Str::startsWith($param, ['tag=discussion_', 'tag=discussions_']), ); if (empty($discussionParam)) { return $response; diff --git a/src/LSCache.php b/src/LSCache.php index 17a7ec0..e7afca5 100644 --- a/src/LSCache.php +++ b/src/LSCache.php @@ -2,6 +2,8 @@ namespace ACPL\FlarumCache; +use Illuminate\Support\Str; + class LSCache { const VARY_COOKIE = 'lscache_vary'; @@ -9,6 +11,6 @@ class LSCache public static function extractRootRouteName(string $name): string { - return explode('.', $name, 2)[0]; + return Str::singular(explode('.', $name, 2)[0]); } } diff --git a/src/LSCacheHeadersEnum.php b/src/LSCacheHeader.php similarity index 86% rename from src/LSCacheHeadersEnum.php rename to src/LSCacheHeader.php index 4783fda..8d6d0e5 100644 --- a/src/LSCacheHeadersEnum.php +++ b/src/LSCacheHeader.php @@ -2,7 +2,7 @@ namespace ACPL\FlarumCache; -final class LSCacheHeadersEnum +final class LSCacheHeader { const CACHE_CONTROL = 'X-LiteSpeed-Cache-Control'; const PURGE = 'X-LiteSpeed-Purge'; diff --git a/src/Listener/AbstractCachePurgeListener.php b/src/Listener/AbstractCachePurgeListener.php new file mode 100644 index 0000000..4ae98f0 --- /dev/null +++ b/src/Listener/AbstractCachePurgeListener.php @@ -0,0 +1,19 @@ +addPurgeData($event); + $this->purger->executePurge(); + } + + abstract protected function addPurgeData(Dispatcher $event): void; +} diff --git a/src/Listener/AbstractCachePurgeSubscriber.php b/src/Listener/AbstractCachePurgeSubscriber.php new file mode 100644 index 0000000..5be6195 --- /dev/null +++ b/src/Listener/AbstractCachePurgeSubscriber.php @@ -0,0 +1,21 @@ +listen($event, function ($eventInstance) use ($handler) { + $handler($eventInstance); + $this->purger->executePurge(); + }); + } +} diff --git a/src/Listener/ClearingCacheListener.php b/src/Listener/ClearingCacheListener.php index 43b4529..d75135b 100644 --- a/src/Listener/ClearingCacheListener.php +++ b/src/Listener/ClearingCacheListener.php @@ -2,30 +2,21 @@ namespace ACPL\FlarumCache\Listener; -use ACPL\FlarumCache\Command\LSCacheClearCommand; +use ACPL\FlarumCache\Utility\LSCachePurger; use Flarum\Settings\SettingsRepositoryInterface; -use Symfony\Component\Console\Exception\ExceptionInterface; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\NullOutput; +use Illuminate\Contracts\Events\Dispatcher; -class ClearingCacheListener +class ClearingCacheListener extends AbstractCachePurgeListener { - private LSCacheClearCommand $command; - private SettingsRepositoryInterface $settings; - - public function __construct(LSCacheClearCommand $command, SettingsRepositoryInterface $settings) + public function __construct(protected LSCachePurger $purger, protected SettingsRepositoryInterface $settings) { - $this->command = $command; - $this->settings = $settings; + parent::__construct($this->purger); } - /** - * @throws ExceptionInterface - */ - public function handle(): void + protected function addPurgeData(Dispatcher $event): void { if ($this->settings->get('acpl-lscache.clearing_cache_listener')) { - $this->command->run(new ArrayInput([]), new NullOutput()); + $this->purger->addPurgePath('*'); } } } diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php new file mode 100644 index 0000000..833c637 --- /dev/null +++ b/src/Listener/DiscussionEventSubscriber.php @@ -0,0 +1,43 @@ +addPurgeListener($events, Deleted::class, [$this, 'handleDeleted']); + + $shared = [Hidden::class, Started::class, Restored::class, Renamed::class]; + foreach ($shared as $method) { + $this->addPurgeListener($events, $method, [$this, 'handle']); + } + } + + protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void + { + $this->purger->addPurgeTags([ + 'default', + 'index', + 'discussions.index', + "discussion_{$event->discussion->id}", + "user_{$event->actor->id}", + "user_{$event->actor->username}", + ]); + } + + protected function handleDeleted(Deleted $event): void + { + // If discussion was hidden before, there is no need to purge cache, because it is not visible for guests anyway + if ($event->discussion->hidden_at === null) { + $this->handle($event); + } + } +} diff --git a/src/Listener/UpdateSettings.php b/src/Listener/UpdateSettings.php deleted file mode 100644 index ee26d6d..0000000 --- a/src/Listener/UpdateSettings.php +++ /dev/null @@ -1,38 +0,0 @@ -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']) { - $this->cacheClearCommand->run(new ArrayInput([]), new NullOutput()); - } - } -} diff --git a/src/Listener/UpdateSettingsListener.php b/src/Listener/UpdateSettingsListener.php new file mode 100644 index 0000000..5acf50a --- /dev/null +++ b/src/Listener/UpdateSettingsListener.php @@ -0,0 +1,29 @@ +settings['acpl-lscache.drop_qs'])) { + $this->htaccessManager->updateHtaccess(); + } + + // If the LSCache is being disabled, initiate a cache purge operation. + if (isset($event->settings['acpl-lscache.cache_enabled']) && ! $event->settings['acpl-lscache.cache_enabled']) { + $this->purger->addPurgePath('*'); + $this->purger->executePurge(); + } + } +} diff --git a/src/Abstract/CacheTagsMiddleware.php b/src/Middleware/AbstractCacheTagsMiddleware.php similarity index 74% rename from src/Abstract/CacheTagsMiddleware.php rename to src/Middleware/AbstractCacheTagsMiddleware.php index 4131189..3aac08e 100644 --- a/src/Abstract/CacheTagsMiddleware.php +++ b/src/Middleware/AbstractCacheTagsMiddleware.php @@ -1,21 +1,21 @@ hasHeader(LSCacheHeadersEnum::TAG)) { + if ($response->hasHeader(LSCacheHeader::TAG)) { $newTags = array_merge( - explode(',', $response->getHeaderLine(LSCacheHeadersEnum::TAG)), - $newTags + explode(',', $response->getHeaderLine(LSCacheHeader::TAG)), + $newTags, ); } $newTags = array_unique($newTags); - return $response->withHeader(LSCacheHeadersEnum::TAG, implode(',', $newTags)); + return $response->withHeader(LSCacheHeader::TAG, implode(',', $newTags)); } } diff --git a/src/Abstract/PurgeMiddleware.php b/src/Middleware/AbstractPurgeCacheMiddleware.php similarity index 60% rename from src/Abstract/PurgeMiddleware.php rename to src/Middleware/AbstractPurgeCacheMiddleware.php index fdfb387..c47a68e 100644 --- a/src/Abstract/PurgeMiddleware.php +++ b/src/Middleware/AbstractPurgeCacheMiddleware.php @@ -1,26 +1,24 @@ settings = $settings; } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface @@ -35,17 +33,6 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface } $this->currentRouteName = $request->getAttribute('routeName'); - $this->isDiscussion = str_starts_with($this->currentRouteName, 'discussions'); - $this->isPost = str_starts_with($this->currentRouteName, 'posts'); - - // If this is just an update of the last read post, there is no point in clearing the public cache - if ($this->isDiscussion && Arr::get( - $request->getParsedBody(), - 'data.attributes.lastReadPostNumber' - ) - ) { - return $response; - } return $this->processPurge($request, $handler, $response); } @@ -53,13 +40,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface abstract protected function processPurge( ServerRequestInterface $request, RequestHandlerInterface $handler, - ResponseInterface $response + ResponseInterface $response, ): ResponseInterface; protected function addPurgeParamsToResponse(ResponseInterface $response, array $newPurgeParams): ResponseInterface { - if ($response->hasHeader(LSCacheHeadersEnum::PURGE)) { - $existingPurgeParams = explode(',', $response->getHeaderLine(LSCacheHeadersEnum::PURGE)); + if ($response->hasHeader(LSCacheHeader::PURGE)) { + $existingPurgeParams = explode(',', $response->getHeaderLine(LSCacheHeader::PURGE)); $newPurgeParams = array_unique(array_merge($existingPurgeParams, $newPurgeParams)); } @@ -71,7 +58,7 @@ protected function addPurgeParamsToResponse(ResponseInterface $response, array $ array_unshift($newPurgeParams, 'stale'); } - return $response->withHeader(LSCacheHeadersEnum::PURGE, implode(',', $newPurgeParams)); + return $response->withHeader(LSCacheHeader::PURGE, implode(',', $newPurgeParams)); } protected function getRouteParams(ServerRequestInterface $request): array diff --git a/src/Middleware/LSCacheControlMiddleware.php b/src/Middleware/CacheControlMiddleware.php similarity index 84% rename from src/Middleware/LSCacheControlMiddleware.php rename to src/Middleware/CacheControlMiddleware.php index a2ab400..4cc3cd3 100644 --- a/src/Middleware/LSCacheControlMiddleware.php +++ b/src/Middleware/CacheControlMiddleware.php @@ -2,7 +2,7 @@ namespace ACPL\FlarumCache\Middleware; -use ACPL\FlarumCache\LSCacheHeadersEnum; +use ACPL\FlarumCache\LSCacheHeader; use Flarum\Http\RequestUtil; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Config\Repository as ConfigRepository; @@ -12,7 +12,7 @@ use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -class LSCacheControlMiddleware implements MiddlewareInterface +class CacheControlMiddleware implements MiddlewareInterface { private SettingsRepositoryInterface $settings; private array $session; @@ -32,18 +32,18 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $this->withCacheControlHeader($response, 'no-cache'); } - if (! in_array($method, ['GET', 'HEAD']) || $response->hasHeader(LSCacheHeadersEnum::CACHE_CONTROL)) { + if (! in_array($method, ['GET', 'HEAD']) || $response->hasHeader(LSCacheHeader::CACHE_CONTROL)) { return $response; } $routeName = $request->getAttribute('routeName'); - //Exclude FriendsOfFlarum/OAuth routes + // Exclude FriendsOfFlarum/OAuth routes if (Str::startsWith($routeName, ['auth', 'fof-oauth'])) { return $this->withCacheControlHeader($response, 'no-cache'); } - //Exclude paths specified in settings + // Exclude paths specified in settings $excludedPaths = Str::of($this->settings->get('acpl-lscache.cache_exclude')); if ($excludedPaths->isNotEmpty()) { $excludedPathsArr = $excludedPaths->explode("\n"); @@ -56,25 +56,25 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface } } - //Exclude purge API route + // Exclude purge API route if ($routeName === 'lscache.purge') { return $this->withCacheControlHeader($response, 'no-cache'); } - //Cache CSRF privately + // Cache CSRF privately if ($routeName === 'lscache.csrf') { // 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) + 'private,max-age='.(($this->session['lifetime'] * 60) - 120), ); } $lscacheParams = []; - //Guest only cache for now + // Guest-only cache $user = RequestUtil::getActor($request); if ($user->isGuest()) { $lscacheParams[] = 'public'; @@ -85,14 +85,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $lscacheParams[] = 'no-cache'; } - //TODO user group cache vary https://docs.litespeedtech.com/lscache/devguide/#cache-vary - //TODO private cache - return $this->withCacheControlHeader($response, implode(',', $lscacheParams)); } private function withCacheControlHeader(ResponseInterface $response, string $paramsStr): ResponseInterface { - return $response->withHeader(LSCacheHeadersEnum::CACHE_CONTROL, $paramsStr); + return $response->withHeader(LSCacheHeader::CACHE_CONTROL, $paramsStr); } } diff --git a/src/Middleware/LSCachePurgeMiddleware.php b/src/Middleware/LSCachePurgeMiddleware.php deleted file mode 100644 index 40c82d6..0000000 --- a/src/Middleware/LSCachePurgeMiddleware.php +++ /dev/null @@ -1,100 +0,0 @@ -currentRouteName; - - $purgeParams = []; - - $params = $this->getRouteParams($request); - - $isDiscussion = $this->isDiscussion; - $isPost = $this->isPost; - - $body = $request->getParsedBody(); - - if ($isDiscussion || $isPost) { - $purgeList = $this->settings->get('acpl-lscache.purge_on_discussion_update'); - if (! empty($purgeList)) { - $purgeList = explode("\n", $purgeList); - // Get only valid items - $purgeList = array_filter($purgeList, fn ($item) => Str::startsWith($item, ['/', 'tag='])); - $purgeParams = array_merge($purgeParams, $purgeList); - } - - // If this is a post update, we don't need to clear the home page cache unless the post is hidden - $isPostUpdate = $routeName === 'posts.update'; - if (($isPostUpdate && Arr::has($body, 'data.attributes.isHidden')) || ! $isPostUpdate) { - array_push($purgeParams, 'tag=default', 'tag=index', 'tag=discussions.index'); - } - - // User profile cache - $response->getBody()->rewind(); - $payload = json_decode($response->getBody()->getContents(), true); - - if (isset($payload, $payload['included'])) { - $userData = Arr::first($payload['included'], fn ($value, $key) => $value['type'] === 'users'); - if ($userData) { - $userId = $userData['id']; - $userName = Arr::get($userData, 'attributes.username'); - - array_push( - $purgeParams, - "tag=user_$userId", - "tag=user_$userName", - "tag=users_$userId", - "tag=users_$userName" - ); - } - } - } - - if ($isPost) { - $discussionId = Arr::get($body, 'data.relationships.discussion.data.id'); - - if (! $discussionId) { - // When an existing post is edited or deleted - $postId = Arr::get($body, 'data.id'); - - if ($postId) { - $discussionId = Post::find($postId)->discussion_id; - } - } - - if ($discussionId) { - array_push($purgeParams, "tag=discussions_$discussionId", "tag=discussion_$discussionId"); - } - } - - if (Str::endsWith($routeName, ['.create', '.update', '.delete'])) { - $rootRouteName = LSCache::extractRootRouteName($routeName); - - // discussions.index is handled earlier - if (! $isDiscussion) { - $purgeParams[] = "tag=$rootRouteName.index"; - } - - if (! empty($params) && ! empty($params['id'])) { - $purgeParams[] = "tag={$rootRouteName}_{$params['id']}"; - } - } - - return $this->addPurgeParamsToResponse($response, $purgeParams); - } -} diff --git a/src/Middleware/LSTagsMiddleware.php b/src/Middleware/LSTagsMiddlewareAbstract.php similarity index 90% rename from src/Middleware/LSTagsMiddleware.php rename to src/Middleware/LSTagsMiddlewareAbstract.php index e2d82d6..a0ee5ca 100644 --- a/src/Middleware/LSTagsMiddleware.php +++ b/src/Middleware/LSTagsMiddlewareAbstract.php @@ -2,18 +2,17 @@ namespace ACPL\FlarumCache\Middleware; -use ACPL\FlarumCache\Abstract\CacheTagsMiddleware; use ACPL\FlarumCache\LSCache; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -class LSTagsMiddleware extends CacheTagsMiddleware +class LSTagsMiddlewareAbstract extends AbstractCacheTagsMiddleware { protected function processTags( ServerRequestInterface $request, RequestHandlerInterface $handler, - ResponseInterface $response + ResponseInterface $response, ): ResponseInterface { $routeName = $this->currentRouteName; $params = $request->getAttribute('routeParameters'); diff --git a/src/Middleware/LoginMiddleware.php b/src/Middleware/LoginMiddleware.php index 11e320d..24478dc 100644 --- a/src/Middleware/LoginMiddleware.php +++ b/src/Middleware/LoginMiddleware.php @@ -15,12 +15,10 @@ class LoginMiddleware implements MiddlewareInterface { - private CookieFactory $cookie; private array $session; - public function __construct(CookieFactory $cookie, ConfigRepository $config) + public function __construct(protected CookieFactory $cookie, ConfigRepository $config) { - $this->cookie = $cookie; $this->session = $config->get('session'); } @@ -43,7 +41,7 @@ private function withVaryCookie(Response $response, Session $session): Response { return FigResponseCookies::set( $response, - $this->cookie->make(LSCache::VARY_COOKIE, $session->token(), $this->session['lifetime'] * 60) + $this->cookie->make(LSCache::VARY_COOKIE, $session->token(), $this->session['lifetime'] * 60), ); } } diff --git a/src/Middleware/LogoutMiddleware.php b/src/Middleware/LogoutMiddleware.php index b181e91..7dbe170 100644 --- a/src/Middleware/LogoutMiddleware.php +++ b/src/Middleware/LogoutMiddleware.php @@ -3,7 +3,7 @@ namespace ACPL\FlarumCache\Middleware; use ACPL\FlarumCache\LSCache; -use ACPL\FlarumCache\LSCacheHeadersEnum; +use ACPL\FlarumCache\LSCacheHeader; use Dflydev\FigCookies\FigResponseCookies; use Flarum\Http\CookieFactory; use Illuminate\Contracts\Session\Session; @@ -16,18 +16,13 @@ class LogoutMiddleware implements MiddlewareInterface { - private CookieFactory $cookie; - - public function __construct(CookieFactory $cookie) - { - $this->cookie = $cookie; - } + public function __construct(protected CookieFactory $cookie) { } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $response = $handler->handle($request); if ($request->getAttribute('routeName') === 'logout' && $response instanceof RedirectResponse) { - $response = $response->withHeader(LSCacheHeadersEnum::CACHE_CONTROL, 'no-cache'); + $response = $response->withHeader(LSCacheHeader::CACHE_CONTROL, 'no-cache'); return $this->withExpiredVaryCookie($response, $request->getAttribute('session')); } @@ -39,7 +34,7 @@ private function withExpiredVaryCookie(Response $response, Session $session): Re { return FigResponseCookies::set( FigResponseCookies::remove($response, LSCache::VARY_COOKIE), - $this->cookie->make(LSCache::VARY_COOKIE, $session->token())->expire() + $this->cookie->make(LSCache::VARY_COOKIE, $session->token())->expire(), ); } } diff --git a/src/Middleware/PurgeCacheMiddleware.php b/src/Middleware/PurgeCacheMiddleware.php new file mode 100644 index 0000000..c08ed5d --- /dev/null +++ b/src/Middleware/PurgeCacheMiddleware.php @@ -0,0 +1,51 @@ +getPurgeParamsFromCachePurger(); + $purgeParams = array_merge($purgeParams, $this->getPurgeParamsFromRoute($request)); + + return $this->addPurgeParamsToResponse($response, array_unique($purgeParams)); + } + + private function getPurgeParamsFromCachePurger(): array + { + $purgeData = $this->cachePurger->getPurgeData(); + $paths = $purgeData['paths'] ?? []; + $tags = array_map(fn ($tag) => "tag=$tag", $purgeData['tags'] ?? []); + + return array_merge($paths, $tags); + } + + private function getPurgeParamsFromRoute(ServerRequestInterface $request): array + { + $routeName = $this->currentRouteName; + $rootRouteName = LSCache::extractRootRouteName($routeName); + $params = $this->getRouteParams($request); + + if (! empty($params['id']) && $this->shouldPurgeRoute($rootRouteName, $routeName)) { + return ["tag={$rootRouteName}_{$params['id']}"]; + } + + return []; + } + + private function shouldPurgeRoute(string $rootRouteName, string $routeName): bool + { + return ! $this->cachePurger::isResourceSupportedByEvent($rootRouteName) + && Str::endsWith($routeName, ['.create', '.update', '.delete']); + } +} diff --git a/src/Middleware/VaryCookieMiddleware.php b/src/Middleware/VaryCookieMiddleware.php index 2ea2679..9d83827 100644 --- a/src/Middleware/VaryCookieMiddleware.php +++ b/src/Middleware/VaryCookieMiddleware.php @@ -3,7 +3,7 @@ namespace ACPL\FlarumCache\Middleware; use ACPL\FlarumCache\LSCache; -use ACPL\FlarumCache\LSCacheHeadersEnum; +use ACPL\FlarumCache\LSCacheHeader; use Dflydev\FigCookies\FigResponseCookies; use Flarum\Http\CookieFactory; use Flarum\Http\RequestUtil; @@ -17,12 +17,10 @@ class VaryCookieMiddleware implements MiddlewareInterface { - private CookieFactory $cookie; private array $session; - public function __construct(CookieFactory $cookie, ConfigRepository $config) + public function __construct(protected CookieFactory $cookie, ConfigRepository $config) { - $this->cookie = $cookie; $this->session = $config->get('session'); } @@ -35,7 +33,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $response = $handler->handle($request); $response = $response->withHeader( - LSCacheHeadersEnum::VARY, + LSCacheHeader::VARY, "cookie={$this->cookie->getName(LSCache::VARY_COOKIE)},cookie={$this->cookie->getName('remember')},cookie=locale", ); @@ -56,7 +54,7 @@ private function withVaryCookie(Response $response, ?Session $session): Response return FigResponseCookies::set( $response, - $this->cookie->make(LSCache::VARY_COOKIE, $session->token(), $this->session['lifetime'] * 60) + $this->cookie->make(LSCache::VARY_COOKIE, $session->token(), $this->session['lifetime'] * 60), ); } } From 7098ac777b5bb3dc1bdaafd9c4e2490de3ef1b03 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 7 Sep 2024 19:05:18 +0000 Subject: [PATCH 03/38] Apply fixes from StyleCI --- src/Listener/AbstractCachePurgeListener.php | 4 +++- src/Listener/AbstractCachePurgeSubscriber.php | 4 +++- src/Listener/DiscussionEventSubscriber.php | 4 ++-- src/Listener/UpdateSettingsListener.php | 4 +++- src/Middleware/AbstractPurgeCacheMiddleware.php | 3 +-- src/Middleware/LogoutMiddleware.php | 4 +++- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Listener/AbstractCachePurgeListener.php b/src/Listener/AbstractCachePurgeListener.php index 4ae98f0..da1c57b 100644 --- a/src/Listener/AbstractCachePurgeListener.php +++ b/src/Listener/AbstractCachePurgeListener.php @@ -7,7 +7,9 @@ abstract class AbstractCachePurgeListener { - public function __construct(protected LSCachePurger $purger) { } + public function __construct(protected LSCachePurger $purger) + { + } protected function handle(Dispatcher $event): void { diff --git a/src/Listener/AbstractCachePurgeSubscriber.php b/src/Listener/AbstractCachePurgeSubscriber.php index 5be6195..c9083f0 100644 --- a/src/Listener/AbstractCachePurgeSubscriber.php +++ b/src/Listener/AbstractCachePurgeSubscriber.php @@ -7,7 +7,9 @@ abstract class AbstractCachePurgeSubscriber { - public function __construct(protected LSCachePurger $purger) { } + public function __construct(protected LSCachePurger $purger) + { + } abstract public function subscribe(Dispatcher $events): void; diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index 833c637..e2e627a 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -4,9 +4,9 @@ use Flarum\Discussion\Event\Deleted; use Flarum\Discussion\Event\Hidden; -use Flarum\Discussion\Event\Started; -use Flarum\Discussion\Event\Restored; use Flarum\Discussion\Event\Renamed; +use Flarum\Discussion\Event\Restored; +use Flarum\Discussion\Event\Started; use Illuminate\Contracts\Events\Dispatcher; class DiscussionEventSubscriber extends AbstractCachePurgeSubscriber diff --git a/src/Listener/UpdateSettingsListener.php b/src/Listener/UpdateSettingsListener.php index 5acf50a..eb4ef84 100644 --- a/src/Listener/UpdateSettingsListener.php +++ b/src/Listener/UpdateSettingsListener.php @@ -9,7 +9,9 @@ class UpdateSettingsListener { - public function __construct(protected HtaccessManager $htaccessManager, protected LSCachePurger $purger) { } + public function __construct(protected HtaccessManager $htaccessManager, protected LSCachePurger $purger) + { + } /** * @throws FileNotFoundException diff --git a/src/Middleware/AbstractPurgeCacheMiddleware.php b/src/Middleware/AbstractPurgeCacheMiddleware.php index c47a68e..f5206a2 100644 --- a/src/Middleware/AbstractPurgeCacheMiddleware.php +++ b/src/Middleware/AbstractPurgeCacheMiddleware.php @@ -17,8 +17,7 @@ abstract class AbstractPurgeCacheMiddleware implements MiddlewareInterface public function __construct( protected SettingsRepositoryInterface $settings, protected LSCachePurger $cachePurger, - ) - { + ) { } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/src/Middleware/LogoutMiddleware.php b/src/Middleware/LogoutMiddleware.php index 7dbe170..dabc203 100644 --- a/src/Middleware/LogoutMiddleware.php +++ b/src/Middleware/LogoutMiddleware.php @@ -16,7 +16,9 @@ class LogoutMiddleware implements MiddlewareInterface { - public function __construct(protected CookieFactory $cookie) { } + public function __construct(protected CookieFactory $cookie) + { + } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { From d68515d82dff07d03b4fb323908216a7d886d667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:06:24 +0200 Subject: [PATCH 04/38] fix: commit missing file --- src/Utility/LSCachePurger.php | 96 +++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/Utility/LSCachePurger.php diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php new file mode 100644 index 0000000..c3670a2 --- /dev/null +++ b/src/Utility/LSCachePurger.php @@ -0,0 +1,96 @@ + $paths + */ + public function addPurgePaths(array $paths): void + { + self::$purgeData['paths'] = array_merge(self::$purgeData['paths'] ?? [], $paths); + } + + public function addPurgeTag(string $tag): void + { + self::$purgeData['tags'][] = $tag; + } + + /** + * @param array $tags + */ + public function addPurgeTags(array $tags): void + { + self::$purgeData['tags'] = array_merge(self::$purgeData['tags'] ?? [], $tags); + } + + public function getPurgeData(): array + { + return self::$purgeData; + } + + public function clearPurgeData(): void + { + self::$purgeData = []; + } + + public function executePurge(): void + { + if (empty(self::$purgeData) || (empty(self::$purgeData['paths']) || empty(self::$purgeData['tags']))) { + return; + } + + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + $this->purgeViaCli(); + } + // else Data will be handled by middleware + } + + private function purgeViaCli(): void + { + $input = []; + + if (! empty(self::$purgeData['paths'])) { + $input['--path'] = self::$purgeData['paths']; + } + + if (! empty(self::$purgeData['tags'])) { + $input['--tag'] = self::$purgeData['tags']; + } + + $this->cacheClearCommand->run(new ArrayInput($input), new NullOutput()); + $this->clearPurgeData(); + } + + public static function isResourceSupportedByEvent(string $resource): bool + { + return in_array($resource, self::$resourcesSupportedByEvent); + } +} From 8ac89523a376e51586a8ebb137869c135efc5d53 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 7 Sep 2024 19:06:33 +0000 Subject: [PATCH 05/38] Apply fixes from StyleCI --- src/Utility/LSCachePurger.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index c3670a2..8663f1d 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -3,9 +3,10 @@ namespace ACPL\FlarumCache\Utility; use ACPL\FlarumCache\Command\LSCacheClearCommand; +use Illuminate\Contracts\Queue\Queue; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; -use Illuminate\Contracts\Queue\Queue; + use const PHP_SAPI; /** From 8dcb8f11e7cb48ddedc43c51dbd99b82865a13fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:07:36 +0200 Subject: [PATCH 06/38] ci: update PHP version --- .github/workflows/backend.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index e6fcd89..b48d6ba 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -8,6 +8,6 @@ jobs: with: enable_backend_testing: false enable_phpstan: true - php_versions: '["8.0", "8.1", "8.2", "8.3"]' + php_versions: '["8.1", "8.2", "8.3"]' backend_directory: . From dd7bdf850ad887a92120ab8e1ad51a7c15ac753f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 13:32:35 +0200 Subject: [PATCH 07/38] feat: add Post event liteners --- extend.php | 2 + src/Listener/DiscussionEventSubscriber.php | 12 +++--- src/Listener/PostEventSubscriber.php | 46 ++++++++++++++++++++++ src/Middleware/PurgeCacheMiddleware.php | 5 ++- 4 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/Listener/PostEventSubscriber.php diff --git a/extend.php b/extend.php index 2219005..d0be41c 100644 --- a/extend.php +++ b/extend.php @@ -20,6 +20,7 @@ use ACPL\FlarumCache\Compatibility\v17development\FlarumBlog\FlarumBlogAbstractPurgeCacheMiddleware; use ACPL\FlarumCache\Listener\ClearingCacheListener; use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; +use ACPL\FlarumCache\Listener\PostEventSubscriber; use ACPL\FlarumCache\Middleware\CacheControlMiddleware; use ACPL\FlarumCache\Middleware\LoginMiddleware; use ACPL\FlarumCache\Middleware\LogoutMiddleware; @@ -75,6 +76,7 @@ (new Extend\Event)->listen(ClearingCache::class, ClearingCacheListener::class), (new Extend\Event)->subscribe(DiscussionEventSubscriber::class), + (new Extend\Event)->subscribe(PostEventSubscriber::class), /*// Compatibility with extensions (new Extend\Conditional) diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index e2e627a..a758921 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -13,12 +13,12 @@ class DiscussionEventSubscriber extends AbstractCachePurgeSubscriber { public function subscribe(Dispatcher $events): void { - $this->addPurgeListener($events, Deleted::class, [$this, 'handleDeleted']); - $shared = [Hidden::class, Started::class, Restored::class, Renamed::class]; - foreach ($shared as $method) { - $this->addPurgeListener($events, $method, [$this, 'handle']); + foreach ($shared as $event) { + $this->addPurgeListener($events, $event, [$this, 'handle']); } + + $this->addPurgeListener($events, Deleted::class, [$this, 'handleDeleted']); } protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void @@ -28,8 +28,8 @@ protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void 'index', 'discussions.index', "discussion_{$event->discussion->id}", - "user_{$event->actor->id}", - "user_{$event->actor->username}", + "user_{$event->discussion->user->id}", + "user_{$event->discussion->user->username}", ]); } diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php new file mode 100644 index 0000000..e8c51a3 --- /dev/null +++ b/src/Listener/PostEventSubscriber.php @@ -0,0 +1,46 @@ +addPurgeListener($events, $event, [$this, 'handle']); + } + + $this->addPurgeListener($events, Revised::class, [$this, 'handleRevised']); + } + + protected function handle(Hidden|Posted|Restored $event): void + { + $this->purger->addPurgeTags([ + 'default', + 'index', + 'posts.index', + 'discussions.index', + "discussion_{$event->post->discussion_id}", + "user_{$event->post->user_id}", + "user_{$event->post->user_id}", + ]); + } + + protected function handleRevised(Revised $event): void + { + // No need to purge homepage cache when post is revised + $this->purger->addPurgeTags([ + 'posts.index', + "discussion_{$event->post->discussion_id}", + "user_{$event->post->user_id}", + "user_{$event->post->user_id}", + ]); + } +} diff --git a/src/Middleware/PurgeCacheMiddleware.php b/src/Middleware/PurgeCacheMiddleware.php index c08ed5d..1f475bb 100644 --- a/src/Middleware/PurgeCacheMiddleware.php +++ b/src/Middleware/PurgeCacheMiddleware.php @@ -16,7 +16,8 @@ protected function processPurge( ResponseInterface $response, ): ResponseInterface { $purgeParams = $this->getPurgeParamsFromCachePurger(); - $purgeParams = array_merge($purgeParams, $this->getPurgeParamsFromRoute($request)); + $purgeParams = array_merge($purgeParams, $this->getPurgeParamsForRoute($request)); + $this->cachePurger->clearPurgeData(); return $this->addPurgeParamsToResponse($response, array_unique($purgeParams)); } @@ -30,7 +31,7 @@ private function getPurgeParamsFromCachePurger(): array return array_merge($paths, $tags); } - private function getPurgeParamsFromRoute(ServerRequestInterface $request): array + private function getPurgeParamsForRoute(ServerRequestInterface $request): array { $routeName = $this->currentRouteName; $rootRouteName = LSCache::extractRootRouteName($routeName); From 0b60528644621a5544aaec017f7adb89f76095f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 13:33:52 +0200 Subject: [PATCH 08/38] perf: enable native_function_invocation --- .styleci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.styleci.yml b/.styleci.yml index 8806a54..fc5bca0 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -2,6 +2,7 @@ preset: recommended enabled: - logical_not_operators_with_successor_space + - native_function_invocation disabled: - align_double_arrow From 783c725dcba61ba45a05de1ab98afb63a43e57ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 13:35:04 +0200 Subject: [PATCH 09/38] fix: remove risky function --- .styleci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.styleci.yml b/.styleci.yml index fc5bca0..8806a54 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -2,7 +2,6 @@ preset: recommended enabled: - logical_not_operators_with_successor_space - - native_function_invocation disabled: - align_double_arrow From 17135d83f811113fe4cd6b2a516c2a51c768f3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 14:12:53 +0200 Subject: [PATCH 10/38] feat: add User event listeners --- extend.php | 2 ++ src/Listener/UserEventSubscriber.php | 35 ++++++++++++++++++++++++++++ src/Utility/LSCachePurger.php | 2 +- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/Listener/UserEventSubscriber.php diff --git a/extend.php b/extend.php index d0be41c..e6d8839 100644 --- a/extend.php +++ b/extend.php @@ -21,6 +21,7 @@ use ACPL\FlarumCache\Listener\ClearingCacheListener; use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; use ACPL\FlarumCache\Listener\PostEventSubscriber; +use ACPL\FlarumCache\Listener\UserEventSubscriber; use ACPL\FlarumCache\Middleware\CacheControlMiddleware; use ACPL\FlarumCache\Middleware\LoginMiddleware; use ACPL\FlarumCache\Middleware\LogoutMiddleware; @@ -77,6 +78,7 @@ (new Extend\Event)->subscribe(DiscussionEventSubscriber::class), (new Extend\Event)->subscribe(PostEventSubscriber::class), + (new Extend\Event)->subscribe(UserEventSubscriber::class), /*// Compatibility with extensions (new Extend\Conditional) diff --git a/src/Listener/UserEventSubscriber.php b/src/Listener/UserEventSubscriber.php new file mode 100644 index 0000000..17f02f0 --- /dev/null +++ b/src/Listener/UserEventSubscriber.php @@ -0,0 +1,35 @@ +addPurgeListener($events, $event, [$this, 'handleUserWithPosts']); + } + } + + /** Purge discussions where user has posted, so new user data is visible there */ + public function handleUserWithPosts(AvatarChanged|GroupsChanged|Renamed $event): void + { + // TODO: If user has a lot discussion chunk it and push to the queue job + $discussions = $event->user->posts()->getRelation('discussion')->pluck('id')->toArray(); + + $this->purger->addPurgeTags([ + "user_{$event->user->id}", + "user_{$event->user->username}", + 'posts.index', + 'discussions.index', + ...array_map(fn ($id) => "discussion_$id", $discussions), + ]); + } +} diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index 8663f1d..33b6a1c 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -20,7 +20,7 @@ class LSCachePurger /** * @var array|string[] */ - public static array $resourcesSupportedByEvent = ['discussion', 'post']; + public static array $resourcesSupportedByEvent = ['discussion', 'post', 'user']; public function __construct(protected readonly LSCacheClearCommand $cacheClearCommand, protected Queue $queue) { From 9d9a5fb7f587cd898a2dc8bf93682f387c125549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 14:48:44 +0200 Subject: [PATCH 11/38] feat: add support for flarum/approval --- composer.json | 3 ++- extend.php | 1 + src/Listener/DiscussionEventSubscriber.php | 15 ++++++++++++++- src/Listener/PostEventSubscriber.php | 22 ++++++++++++++++++++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 5645531..ceaee84 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "require-dev": { "flarum/phpstan": "^1.8", "flarum/tags": "*", - "v17development/flarum-blog": "^0.7.7" + "v17development/flarum-blog": "^0.7.7", + "flarum/approval": "^1.8" }, "suggest": { "blomstra/flarum-redis": "This library allows using Redis as cache, session and for the queue. https://github.com/blomstra/flarum-redis#set-up" diff --git a/extend.php b/extend.php index e6d8839..f0b21f3 100644 --- a/extend.php +++ b/extend.php @@ -14,6 +14,7 @@ use ACPL\FlarumCache\Api\Controller\LSCacheCsrfResponseController; use ACPL\FlarumCache\Api\Controller\PurgeLSCacheController; use ACPL\FlarumCache\Command\LSCacheClearCommand; +use ACPL\FlarumCache\Compatibility\Flarum\Approval\FlarumApprovalEventSubscriber; use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesAbstractPurgeCacheMiddleware; use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsAbstractPurgeCacheMiddleware; use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradeAbstractPurgeCacheMiddleware; diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index a758921..1d4da71 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -23,6 +23,10 @@ public function subscribe(Dispatcher $events): void protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void { + if (! $this->shouldPurge($event)) { + return; + } + $this->purger->addPurgeTags([ 'default', 'index', @@ -36,8 +40,17 @@ protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void protected function handleDeleted(Deleted $event): void { // If discussion was hidden before, there is no need to purge cache, because it is not visible for guests anyway - if ($event->discussion->hidden_at === null) { + if ($event->discussion->hidden_at === null && $this->shouldPurge($event)) { $this->handle($event); } } + + protected function shouldPurge( + Deleted|Hidden|Started|Restored|Renamed $event, + ): bool { + return ! ( + $event->discussion->is_private + || $event->discussion?->is_approved === false + ); + } } diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index e8c51a3..4d5ec5e 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -2,6 +2,8 @@ namespace ACPL\FlarumCache\Listener; +use Flarum\Approval\Event\PostWasApproved; +use Flarum\Post\Event\Deleted; use Flarum\Post\Event\Hidden; use Flarum\Post\Event\Posted; use Flarum\Post\Event\Restored; @@ -12,7 +14,7 @@ class PostEventSubscriber extends AbstractCachePurgeSubscriber { public function subscribe(Dispatcher $events): void { - $shared = [Hidden::class, Posted::class, Restored::class]; + $shared = [Hidden::class, Posted::class, Restored::class, PostWasApproved::class]; foreach ($shared as $event) { $this->addPurgeListener($events, $event, [$this, 'handle']); } @@ -20,8 +22,12 @@ public function subscribe(Dispatcher $events): void $this->addPurgeListener($events, Revised::class, [$this, 'handleRevised']); } - protected function handle(Hidden|Posted|Restored $event): void + protected function handle(Hidden|Posted|Restored|PostWasApproved $event): void { + if (! $this->shouldPurge($event)) { + return; + } + $this->purger->addPurgeTags([ 'default', 'index', @@ -35,6 +41,10 @@ protected function handle(Hidden|Posted|Restored $event): void protected function handleRevised(Revised $event): void { + if (! $this->shouldPurge($event)) { + return; + } + // No need to purge homepage cache when post is revised $this->purger->addPurgeTags([ 'posts.index', @@ -43,4 +53,12 @@ protected function handleRevised(Revised $event): void "user_{$event->post->user_id}", ]); } + + protected function shouldPurge(Deleted|Hidden|Posted|Restored|Revised|PostWasApproved $event): bool + { + return ! ( + $event->post->discussion->is_private + || $event->post?->is_approved === false + ); + } } From 20113b89a770fbd899b3121d0a25ee1fca0491aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 15:05:03 +0200 Subject: [PATCH 12/38] feat: add support for flarum/likes --- composer.json | 3 +- extend.php | 29 +++-------------- ...larumLikesAbstractPurgeCacheMiddleware.php | 30 ------------------ .../Likes/FlarumLikesEventSubscriber.php | 31 +++++++++++++++++++ 4 files changed, 38 insertions(+), 55 deletions(-) delete mode 100644 src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php create mode 100644 src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php diff --git a/composer.json b/composer.json index ceaee84..e56cb36 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "flarum/phpstan": "^1.8", "flarum/tags": "*", "v17development/flarum-blog": "^0.7.7", - "flarum/approval": "^1.8" + "flarum/approval": "^1.8", + "flarum/likes": "^1.8" }, "suggest": { "blomstra/flarum-redis": "This library allows using Redis as cache, session and for the queue. https://github.com/blomstra/flarum-redis#set-up" diff --git a/extend.php b/extend.php index f0b21f3..7e09bdb 100644 --- a/extend.php +++ b/extend.php @@ -14,11 +14,7 @@ use ACPL\FlarumCache\Api\Controller\LSCacheCsrfResponseController; use ACPL\FlarumCache\Api\Controller\PurgeLSCacheController; use ACPL\FlarumCache\Command\LSCacheClearCommand; -use ACPL\FlarumCache\Compatibility\Flarum\Approval\FlarumApprovalEventSubscriber; -use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesAbstractPurgeCacheMiddleware; -use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsAbstractPurgeCacheMiddleware; -use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradeAbstractPurgeCacheMiddleware; -use ACPL\FlarumCache\Compatibility\v17development\FlarumBlog\FlarumBlogAbstractPurgeCacheMiddleware; +use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesEventSubscriber; use ACPL\FlarumCache\Listener\ClearingCacheListener; use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; use ACPL\FlarumCache\Listener\PostEventSubscriber; @@ -81,23 +77,8 @@ (new Extend\Event)->subscribe(PostEventSubscriber::class), (new Extend\Event)->subscribe(UserEventSubscriber::class), - /*// Compatibility with extensions - (new Extend\Conditional) - ->whenExtensionEnabled('flarum-tags', [ - (new Extend\Middleware('api'))->add(FlarumTagsAbstractPurgeCacheMiddleware::class), - ]) - ->whenExtensionEnabled('flarum-likes', [ - (new Extend\Middleware('api'))->add(FlarumLikesAbstractPurgeCacheMiddleware::class), - ]) - ->whenExtensionEnabled('fof-masquerade', [ - (new Extend\Middleware('api'))->add(FofMasqueradeAbstractPurgeCacheMiddleware::class), - ]) - ->whenExtensionEnabled('v17development-blog', [ - // Using insertBefore enables reading headers set by LSCachePurgeMiddleware, while insertAfter does not. - // This suggests Flarum processes middleware in a reverse order 🤔. - (new Extend\Middleware('api'))->insertBefore( - PurgeCacheMiddleware::class, - FlarumBlogAbstractPurgeCacheMiddleware::class, - ), - ]),*/ + (new Extend\Conditional) + ->whenExtensionEnabled('flarum-likes', [ + (new Extend\Event)->subscribe(FlarumLikesEventSubscriber::class), + ]), ]; diff --git a/src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php b/src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php deleted file mode 100644 index 8dbd63b..0000000 --- a/src/Compatibility/Flarum/Likes/FlarumLikesAbstractPurgeCacheMiddleware.php +++ /dev/null @@ -1,30 +0,0 @@ -currentRouteName !== 'posts.update') { - return $response; - } - - $requestBody = $request->getParsedBody(); - - if (! Arr::has($requestBody, 'data.attributes.isLiked')) { - return $response; - } - - return $this->addPurgeParamsToResponse($response, ['users.index']); - } -} diff --git a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php new file mode 100644 index 0000000..107cfbc --- /dev/null +++ b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php @@ -0,0 +1,31 @@ +addPurgeListener($events, $event, [$this, 'handle']); + } + } + + protected function handle(PostWasLiked|PostWasUnliked $event): void + { + $this->purger->addPurgeTags([ + "posts.index", + "post_{$event->post->id}", + "discussion_{$event->post->discussion->id}", + "user_{$event->post->user->id}", + "user_{$event->post->user->username}", + "user_{$event->user->id}", + "user_{$event->user->username}", + ]); + } +} From 5faf90f8f582c85b9f25cb0c09ef5cd19f40d5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 15:51:21 +0200 Subject: [PATCH 13/38] feat: add support for flarum/tags --- composer.json | 2 +- extend.php | 4 + .../Flarum/Tags/FlarumTagsEventSubscriber.php | 89 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php diff --git a/composer.json b/composer.json index e56cb36..f01a7cb 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ }, "require-dev": { "flarum/phpstan": "^1.8", - "flarum/tags": "*", + "flarum/tags": "^1.8", "v17development/flarum-blog": "^0.7.7", "flarum/approval": "^1.8", "flarum/likes": "^1.8" diff --git a/extend.php b/extend.php index 7e09bdb..424e017 100644 --- a/extend.php +++ b/extend.php @@ -15,6 +15,7 @@ use ACPL\FlarumCache\Api\Controller\PurgeLSCacheController; use ACPL\FlarumCache\Command\LSCacheClearCommand; use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesEventSubscriber; +use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsEventSubscriber; use ACPL\FlarumCache\Listener\ClearingCacheListener; use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; use ACPL\FlarumCache\Listener\PostEventSubscriber; @@ -80,5 +81,8 @@ (new Extend\Conditional) ->whenExtensionEnabled('flarum-likes', [ (new Extend\Event)->subscribe(FlarumLikesEventSubscriber::class), + ]) + ->whenExtensionEnabled('flarum-tags', [ + (new Extend\Event)->subscribe(FlarumTagsEventSubscriber::class), ]), ]; diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php new file mode 100644 index 0000000..81826b9 --- /dev/null +++ b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php @@ -0,0 +1,89 @@ +addPurgeListener($events, DiscussionWasTagged::class, [$this, 'handleDiscussionWasTagged']); + + $discussionEvents = [ + DiscussionDeleted::class, DiscussionHidden::class, DiscussionRenamed::class, DiscussionRestored::class, + DiscussionStarted::class, + ]; + foreach ($discussionEvents as $event) { + $this->addPurgeListener($events, $event, [$this, 'handleDiscussionEvents']); + } + + $postEvents = [PostDeleted::class, PostHidden::class, Posted::class, PostRestored::class]; + foreach ($postEvents as $event) { + $this->addPurgeListener($events, $event, [$this, 'handlePostEvents']); + } + } + + public function handleDiscussionWasTagged(DiscussionWasTagged $event): void + { + $this->purger->addPurgeTags([ + 'default', + 'index', + 'discussions.index', + "discussion_{$event->discussion->id}", + "user_{$event->discussion->user->id}", + "user_{$event->discussion->user->username}", + "tags.index", + ...$this->generateCacheTagsForDiscussionTags($event->discussion), + ]); + } + + public function handleDiscussionEvents( + DiscussionDeleted|DiscussionHidden|DiscussionRenamed|DiscussionRestored|DiscussionStarted $event, + ): void { + if ( + ($event instanceof DiscussionDeleted && $event->discussion->hidden_at !== null) + || $event->discussion->is_approved === false + ) { + return; + } + + $this->purger->addPurgeTags([ + 'tags.index', + ...$this->generateCacheTagsForDiscussionTags($event->discussion), + ]); + } + + public function handlePostEvents(PostDeleted|PostHidden|Posted|PostRestored $event): void + { + if ( + ($event instanceof PostRestored && $event->post->discussion->hidden_at !== null) + || $event->post->discussion->is_approved === false + ) { + return; + } + + $this->purger->addPurgeTags([ + 'tags.index', + ...$this->generateCacheTagsForDiscussionTags($event->post->discussion), + ]); + } + + protected function generateCacheTagsForDiscussionTags(Discussion $discussion): array + { + return $discussion->tags->map(fn (Tag $tag) => "tag_$tag->slug")->toArray(); + } +} From 83ad08515623b5db9590fcf4079aed26d7a31c70 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sun, 8 Sep 2024 13:51:35 +0000 Subject: [PATCH 14/38] Apply fixes from StyleCI --- src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php | 2 +- src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php index 107cfbc..36c7f39 100644 --- a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php +++ b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php @@ -19,7 +19,7 @@ public function subscribe(Dispatcher $events): void protected function handle(PostWasLiked|PostWasUnliked $event): void { $this->purger->addPurgeTags([ - "posts.index", + 'posts.index', "post_{$event->post->id}", "discussion_{$event->post->discussion->id}", "user_{$event->post->user->id}", diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php index 81826b9..924f304 100644 --- a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php +++ b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php @@ -46,7 +46,7 @@ public function handleDiscussionWasTagged(DiscussionWasTagged $event): void "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", - "tags.index", + 'tags.index', ...$this->generateCacheTagsForDiscussionTags($event->discussion), ]); } From b20923888c13b8f20b19c7a8378379e58da1bddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 16:07:50 +0200 Subject: [PATCH 15/38] feat: add support for fof/masquerade --- composer.json | 7 +- extend.php | 4 + ...FlarumTagsAbstractPurgeCacheMiddleware.php | 91 ------------------- ... => FofMasqueradePurgeCacheMiddleware.php} | 4 +- 4 files changed, 10 insertions(+), 96 deletions(-) delete mode 100644 src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php rename src/Compatibility/FriendsOfFlarum/Masquerade/{FofMasqueradeAbstractPurgeCacheMiddleware.php => FofMasqueradePurgeCacheMiddleware.php} (85%) diff --git a/composer.json b/composer.json index f01a7cb..498f13f 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "flarum/tags": "^1.8", "v17development/flarum-blog": "^0.7.7", "flarum/approval": "^1.8", - "flarum/likes": "^1.8" + "flarum/likes": "^1.8", + "fof/masquerade": "^2.1" }, "suggest": { "blomstra/flarum-redis": "This library allows using Redis as cache, session and for the queue. https://github.com/blomstra/flarum-redis#set-up" @@ -56,9 +57,11 @@ "color": "#fff" }, "optional-dependencies": [ + "flarum/approval", "flarum/tags", "flarum/likes", - "fof/masquerade" + "fof/masquerade", + "v17development/flarum-blog" ] }, "flarum-cli": { diff --git a/extend.php b/extend.php index 424e017..9f091b3 100644 --- a/extend.php +++ b/extend.php @@ -16,6 +16,7 @@ use ACPL\FlarumCache\Command\LSCacheClearCommand; use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesEventSubscriber; use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsEventSubscriber; +use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware; use ACPL\FlarumCache\Listener\ClearingCacheListener; use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; use ACPL\FlarumCache\Listener\PostEventSubscriber; @@ -84,5 +85,8 @@ ]) ->whenExtensionEnabled('flarum-tags', [ (new Extend\Event)->subscribe(FlarumTagsEventSubscriber::class), + ]) + ->whenExtensionEnabled('fof-masquerade', [ + (new Extend\Middleware('api'))->add(FofMasqueradePurgeCacheMiddleware::class), ]), ]; diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php b/src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php deleted file mode 100644 index c4a4a7a..0000000 --- a/src/Compatibility/Flarum/Tags/FlarumTagsAbstractPurgeCacheMiddleware.php +++ /dev/null @@ -1,91 +0,0 @@ -url = $url; - parent::__construct($settings); - } - - protected function processPurge( - ServerRequestInterface $request, - RequestHandlerInterface $handler, - ResponseInterface $response, - ): ResponseInterface { - $isDiscussion = $this->isDiscussion; - $isPost = $this->isPost; - - if (! $isDiscussion && ! $isPost) { - return $response; - } - - $body = $request->getParsedBody(); - $routeName = $this->currentRouteName; - - // When a post is edited, there is no need to purge tags cache unless the post is being hidden - if ($routeName === 'posts.update' && ! Arr::has($body, 'data.attributes.isHidden')) { - return $response; - } - - $response->getBody()->rewind(); - $payload = $response->getBody()->getContents(); - $payload = json_decode($payload, true); - - if ($isDiscussion) { - $discussionId = Arr::get($payload, 'data.id'); - } else { - $discussionId = Arr::get($payload, 'data.relationships.discussion.data.id'); - if (! $discussionId) { - $postId = Arr::get($payload, 'data.id'); - if (! $postId) { - return $response; - } - - $discussionId = Post::find($postId)->discussion_id; - } - } - - if (! $discussionId) { - return $response; - } - - $discussion = Discussion::find($discussionId); - if (! $discussion) { - return $response; - } - - /** - * @var Tag[] $tags - * @phpstan-ignore-next-line - */ - $tags = $discussion->tags; - - if (! $tags) { - return $response; - } - - $purgeParams = ['tags.index', 'tags']; - - foreach ($tags as $tag) { - $purgeParams[] = "tag_$tag->slug"; - } - - return $this->addPurgeParamsToResponse($response, $purgeParams); - } -} diff --git a/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradeAbstractPurgeCacheMiddleware.php b/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php similarity index 85% rename from src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradeAbstractPurgeCacheMiddleware.php rename to src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php index 3cd22e0..aad8d34 100644 --- a/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradeAbstractPurgeCacheMiddleware.php +++ b/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php @@ -8,7 +8,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -class FofMasqueradeAbstractPurgeCacheMiddleware extends AbstractPurgeCacheMiddleware +class FofMasqueradePurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { protected function processPurge( ServerRequestInterface $request, @@ -24,9 +24,7 @@ protected function processPurge( $response, [ "tag=user_$user->id", - "tag=users_$user->id", "tag=user_$user->username", - "tag=users_$user->username", "tag=masquerade_$user->id", ], ); From c3963430cdcb3ead8e803d24df9847f5bd471a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sun, 8 Sep 2024 16:28:03 +0200 Subject: [PATCH 16/38] feat: add support for v17development/blog --- extend.php | 4 ++ ...FlarumBlogAbstractPurgeCacheMiddleware.php | 67 ------------------- .../FlarumBlog/FlarumBlogEventSubscriber.php | 23 +++++++ src/Listener/DiscussionEventSubscriber.php | 1 + src/Listener/PostEventSubscriber.php | 1 + 5 files changed, 29 insertions(+), 67 deletions(-) delete mode 100644 src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php create mode 100644 src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php diff --git a/extend.php b/extend.php index 9f091b3..76ca9e1 100644 --- a/extend.php +++ b/extend.php @@ -17,6 +17,7 @@ use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesEventSubscriber; use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsEventSubscriber; use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware; +use ACPL\FlarumCache\Compatibility\v17development\FlarumBlog\FlarumBlogEventSubscriber; use ACPL\FlarumCache\Listener\ClearingCacheListener; use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; use ACPL\FlarumCache\Listener\PostEventSubscriber; @@ -88,5 +89,8 @@ ]) ->whenExtensionEnabled('fof-masquerade', [ (new Extend\Middleware('api'))->add(FofMasqueradePurgeCacheMiddleware::class), + ]) + ->whenExtensionEnabled('v17development-blog', [ + (new Extend\Event)->subscribe(FlarumBlogEventSubscriber::class), ]), ]; diff --git a/src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php b/src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php deleted file mode 100644 index 7ce8d12..0000000 --- a/src/Compatibility/v17development/FlarumBlog/FlarumBlogAbstractPurgeCacheMiddleware.php +++ /dev/null @@ -1,67 +0,0 @@ -isDiscussion; - $isPost = $this->isPost; - - if (! ($isDiscussion || $isPost)) { - return $response; - } - - if ($this->currentRouteName === 'discussions.create') { - $body = $request->getParsedBody(); - if (Arr::has($body, 'data.attributes.blogMeta')) { - return $this->addPurgeParamsToResponse($response, ['tag=blog.overview']); - } - } - - $currentPurgeParams = $response->getHeaderLine(LSCacheHeader::PURGE); - if (empty($currentPurgeParams)) { - return $response; - } - - $newPurgeParams = []; - $currentPurgeParams = explode(',', $currentPurgeParams); - - // Blog extension is using default Flarum discussion api routes, so we can just reuse previous middleware to get the blog post id - $discussionParam = Arr::first( - $currentPurgeParams, - fn (string $param) => Str::startsWith($param, ['tag=discussion_', 'tag=discussions_']), - ); - if (empty($discussionParam)) { - return $response; - } - - if (preg_match('/(\d+)/', $discussionParam, $matches)) { - $discussionId = $matches[1]; - $newPurgeParams[] = 'tag=blog_'.$discussionId; - - // If the previous response wants to purge the index page and this is a blog post, we need to purge the blog overview page as well - if ( - in_array('tag=index', $currentPurgeParams) - && BlogMeta::where('discussion_id', '=', $discussionId)->first() - ) { - $newPurgeParams[] = 'tag=blog.overview'; - } - } - - return $this->addPurgeParamsToResponse($response, $newPurgeParams); - } -} diff --git a/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php b/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php new file mode 100644 index 0000000..5341898 --- /dev/null +++ b/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php @@ -0,0 +1,23 @@ +addPurgeListener($events, BlogMetaSaving::class, [$this, 'handle']); + } + + public function handle(BlogMetaSaving $event): void + { + $this->purger->addPurgeTags([ + 'blog.overview', + "blog_{$event->blogMeta->discussion_id}", + ]); + } +} diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index 1d4da71..5bf1af0 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -34,6 +34,7 @@ protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", + "blog_{$event->discussion->id}", ]); } diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index 4d5ec5e..e9e3f3b 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -36,6 +36,7 @@ protected function handle(Hidden|Posted|Restored|PostWasApproved $event): void "discussion_{$event->post->discussion_id}", "user_{$event->post->user_id}", "user_{$event->post->user_id}", + "blog_{$event->post->discussion->id}", ]); } From 73e2949d54762c5a5324a760e713655595b27dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 21:14:44 +0200 Subject: [PATCH 17/38] feat: add support for clarkwinkelmann/flarum-ext-author-change --- composer.json | 3 +- extend.php | 4 ++ ...kWinkelmannAuthorChangeEventSubscriber.php | 65 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php diff --git a/composer.json b/composer.json index 498f13f..6dd4107 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,8 @@ "v17development/flarum-blog": "^0.7.7", "flarum/approval": "^1.8", "flarum/likes": "^1.8", - "fof/masquerade": "^2.1" + "fof/masquerade": "^2.1", + "clarkwinkelmann/flarum-ext-author-change": "^1.0" }, "suggest": { "blomstra/flarum-redis": "This library allows using Redis as cache, session and for the queue. https://github.com/blomstra/flarum-redis#set-up" diff --git a/extend.php b/extend.php index 76ca9e1..a4bccac 100644 --- a/extend.php +++ b/extend.php @@ -14,6 +14,7 @@ use ACPL\FlarumCache\Api\Controller\LSCacheCsrfResponseController; use ACPL\FlarumCache\Api\Controller\PurgeLSCacheController; use ACPL\FlarumCache\Command\LSCacheClearCommand; +use ACPL\FlarumCache\Compatibility\ClarkWinkelmann\AuthorChange\ClarkWinkelmannAuthorChangeEventSubscriber; use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesEventSubscriber; use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsEventSubscriber; use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware; @@ -92,5 +93,8 @@ ]) ->whenExtensionEnabled('v17development-blog', [ (new Extend\Event)->subscribe(FlarumBlogEventSubscriber::class), + ]) + ->whenExtensionEnabled('clarkwinkelmann-author-change', [ + (new Extend\Event)->subscribe(ClarkWinkelmannAuthorChangeEventSubscriber::class), ]), ]; diff --git a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php new file mode 100644 index 0000000..11edd4a --- /dev/null +++ b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php @@ -0,0 +1,65 @@ +addPurgeListener($events, DiscussionCreateDateChanged::class, [$this, 'handleDiscussion']); + $this->addPurgeListener($events, DiscussionUserChanged::class, [$this, 'handleDiscussionUserChanged']); + $this->addPurgeListener($events, PostCreateDateChanged::class, [$this, 'handlePost']); + $this->addPurgeListener($events, PostEditDateChanged::class, [$this, 'handlePost']); + $this->addPurgeListener($events, PostUserChanged::class, [$this, 'handlePostUserChanged']); + } + + protected function handleDiscussion(DiscussionCreateDateChanged|DiscussionUserChanged $event): void + { + $this->purger->addPurgeTags([ + 'default', + 'index', + 'discussions.index', + "discussion_{$event->discussion->id}", + "user_{$event->discussion->user->id}", + "user_{$event->discussion->user->username}", + ]); + } + + protected function handleDiscussionUserChanged(DiscussionUserChanged $event): void + { + $this->handleDiscussion($event); + $this->purger->addPurgeTags([ + "user_{$event->oldUser->id}", + "user_{$event->oldUser->username}", + ]); + } + + protected function handlePost(PostCreateDateChanged|PostEditDateChanged|PostUserChanged $event): void + { + $this->purger->addPurgeTags([ + "discussion_{$event->post->discussion->id}", + "posts.index", + "post_{$event->post->id}", + "user_{$event->post->user->id}", + "user_{$event->post->user->username}", + ]); + } + + protected function handlePostUserChanged(PostUserChanged $event): void + { + $this->handlePost($event); + $this->purger->addPurgeTags([ + "user_{$event->oldUser->id}", + "user_{$event->oldUser->username}", + ]); + } +} From f65b2b24aebcb64c3a0e7bce1df7dd84d42e9513 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 12 Sep 2024 19:15:00 +0000 Subject: [PATCH 18/38] Apply fixes from StyleCI --- .../ClarkWinkelmannAuthorChangeEventSubscriber.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php index 11edd4a..dc0310c 100644 --- a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php +++ b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php @@ -2,7 +2,6 @@ namespace ACPL\FlarumCache\Compatibility\ClarkWinkelmann\AuthorChange; - use ACPL\FlarumCache\Listener\AbstractCachePurgeSubscriber; use ClarkWinkelmann\AuthorChange\Event\DiscussionCreateDateChanged; use ClarkWinkelmann\AuthorChange\Event\DiscussionUserChanged; @@ -47,7 +46,7 @@ protected function handlePost(PostCreateDateChanged|PostEditDateChanged|PostUser { $this->purger->addPurgeTags([ "discussion_{$event->post->discussion->id}", - "posts.index", + 'posts.index', "post_{$event->post->id}", "user_{$event->post->user->id}", "user_{$event->post->user->username}", From 0e2107723f2694cf0cf47cdb1f1cb1b005c47b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:51:16 +0200 Subject: [PATCH 19/38] feat: add LSCachePurging event --- .../FofMasqueradePurgeCacheMiddleware.php | 27 +++---- .../FlarumBlog/FlarumBlogEventSubscriber.php | 18 +++++ src/Event/LSCachePurging.php | 19 +++++ src/Listener/DiscussionEventSubscriber.php | 1 - src/Listener/PostEventSubscriber.php | 1 - .../AbstractPurgeCacheMiddleware.php | 72 +++++++++++++------ src/Middleware/PurgeCacheMiddleware.php | 29 +------- src/Utility/LSCachePurger.php | 24 +++++-- 8 files changed, 117 insertions(+), 74 deletions(-) create mode 100644 src/Event/LSCachePurging.php diff --git a/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php b/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php index aad8d34..03fc80e 100644 --- a/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php +++ b/src/Compatibility/FriendsOfFlarum/Masquerade/FofMasqueradePurgeCacheMiddleware.php @@ -4,32 +4,23 @@ use ACPL\FlarumCache\Middleware\AbstractPurgeCacheMiddleware; use Flarum\User\User; -use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\RequestHandlerInterface; class FofMasqueradePurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { - protected function processPurge( - ServerRequestInterface $request, - RequestHandlerInterface $handler, - ResponseInterface $response, - ): ResponseInterface { - // Purge user profile cache when updating FriendsOfFlarum/masquerade fields + protected function preparePurgeData(ServerRequestInterface $request): void + { if ($this->currentRouteName === 'masquerade.api.configure.save') { $userID = $this->getRouteParams($request)['id']; $user = User::find($userID); - return $this->addPurgeParamsToResponse( - $response, - [ - "tag=user_$user->id", - "tag=user_$user->username", - "tag=masquerade_$user->id", - ], - ); + if ($user) { + $this->cachePurger->addPurgeTags([ + "user_$user->id", + "user_$user->username", + "masquerade_$user->id", + ]); + } } - - return $response; } } diff --git a/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php b/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php index 5341898..6a1575e 100644 --- a/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php +++ b/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php @@ -2,8 +2,10 @@ namespace ACPL\FlarumCache\Compatibility\v17development\FlarumBlog; +use ACPL\FlarumCache\Event\LSCachePurging; use ACPL\FlarumCache\Listener\AbstractCachePurgeSubscriber; use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Support\Arr; use V17Development\FlarumBlog\Event\BlogMetaSaving; class FlarumBlogEventSubscriber extends AbstractCachePurgeSubscriber @@ -11,6 +13,7 @@ class FlarumBlogEventSubscriber extends AbstractCachePurgeSubscriber public function subscribe(Dispatcher $events): void { $this->addPurgeListener($events, BlogMetaSaving::class, [$this, 'handle']); + $this->addPurgeListener($events, LSCachePurging::class, [$this, 'handleLSCachePurging']); } public function handle(BlogMetaSaving $event): void @@ -20,4 +23,19 @@ public function handle(BlogMetaSaving $event): void "blog_{$event->blogMeta->discussion_id}", ]); } + + /** + * If discussion is detected, also purge blog, because blog is a discussion. + */ + public function handleLSCachePurging(LSCachePurging $event): void + { + if (in_array('index', $event->data['tags'])) { + $this->purger->addPurgeTag('blog.overview'); + } + + $discussion = Arr::first($event->data['tags'], fn (string $tag) => str_starts_with($tag, 'discussion_')); + if ($discussion) { + $this->purger->addPurgeTag('blog_'.explode('_', $discussion)[1]); + } + } } diff --git a/src/Event/LSCachePurging.php b/src/Event/LSCachePurging.php new file mode 100644 index 0000000..14c84b1 --- /dev/null +++ b/src/Event/LSCachePurging.php @@ -0,0 +1,19 @@ +discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", - "blog_{$event->discussion->id}", ]); } diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index e9e3f3b..4d5ec5e 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -36,7 +36,6 @@ protected function handle(Hidden|Posted|Restored|PostWasApproved $event): void "discussion_{$event->post->discussion_id}", "user_{$event->post->user_id}", "user_{$event->post->user_id}", - "blog_{$event->post->discussion->id}", ]); } diff --git a/src/Middleware/AbstractPurgeCacheMiddleware.php b/src/Middleware/AbstractPurgeCacheMiddleware.php index f5206a2..fd6cd74 100644 --- a/src/Middleware/AbstractPurgeCacheMiddleware.php +++ b/src/Middleware/AbstractPurgeCacheMiddleware.php @@ -2,13 +2,13 @@ namespace ACPL\FlarumCache\Middleware; +use ACPL\FlarumCache\Event\LSCachePurging; use ACPL\FlarumCache\LSCacheHeader; use ACPL\FlarumCache\Utility\LSCachePurger; use Flarum\Settings\SettingsRepositoryInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; +use Illuminate\Events\Dispatcher; +use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; +use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface}; abstract class AbstractPurgeCacheMiddleware implements MiddlewareInterface { @@ -17,51 +17,79 @@ abstract class AbstractPurgeCacheMiddleware implements MiddlewareInterface public function __construct( protected SettingsRepositoryInterface $settings, protected LSCachePurger $cachePurger, + protected Dispatcher $events, ) { } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $response = $handler->handle($request); + $this->currentRouteName = $request->getAttribute('routeName'); - if ( - ! in_array($request->getMethod(), ['POST', 'PUT', 'PATCH', 'DELETE']) - || $response->getStatusCode() >= 400 - ) { - return $response; + if ($this->shouldProcessPurge($request, $response)) { + $this->preparePurgeData($request); + $this->dispatchLSCachePurgingEvent(); + $response = $this->addPurgeParamsToResponse($response); } - $this->currentRouteName = $request->getAttribute('routeName'); + return $response; + } - return $this->processPurge($request, $handler, $response); + protected function shouldProcessPurge(ServerRequestInterface $request, ResponseInterface $response): bool + { + return in_array($request->getMethod(), ['POST', 'PUT', 'PATCH', 'DELETE']) + && $response->getStatusCode() < 400; } - abstract protected function processPurge( - ServerRequestInterface $request, - RequestHandlerInterface $handler, - ResponseInterface $response, - ): ResponseInterface; + abstract protected function preparePurgeData(ServerRequestInterface $request): void; - protected function addPurgeParamsToResponse(ResponseInterface $response, array $newPurgeParams): ResponseInterface + protected function addPurgeParamsToResponse(ResponseInterface $response): ResponseInterface { + $purgeData = $this->cachePurger->getPurgeData(); + $newPurgeParams = $this->formatPurgeParams($purgeData); + if ($response->hasHeader(LSCacheHeader::PURGE)) { $existingPurgeParams = explode(',', $response->getHeaderLine(LSCacheHeader::PURGE)); - $newPurgeParams = array_unique(array_merge($existingPurgeParams, $newPurgeParams)); + $newPurgeParams = array_merge($existingPurgeParams, $newPurgeParams); } - if (count($newPurgeParams) < 1) { + if (empty($newPurgeParams)) { return $response; } - if ($this->settings->get('acpl-lscache.serve_stale') && ! array_key_exists('stale', $newPurgeParams)) { - array_unshift($newPurgeParams, 'stale'); + $this->addStaleParamIfNeeded($newPurgeParams); + $this->cachePurger->clearPurgeData(); + + return $response->withHeader(LSCacheHeader::PURGE, implode(',', array_unique($newPurgeParams))); + } + + protected function formatPurgeParams(array $purgeData): array + { + $params = $purgeData['paths'] ?? []; + if (! empty($purgeData['tags'])) { + $params = array_merge( + $params, + array_map(fn (string $tag) => "tag=$tag", $purgeData['tags']), + ); } + return $params; + } - return $response->withHeader(LSCacheHeader::PURGE, implode(',', $newPurgeParams)); + protected function addStaleParamIfNeeded(array &$params): void + { + if ($this->settings->get('acpl-lscache.serve_stale') && ! in_array('stale', $params)) { + array_unshift($params, 'stale'); + } } protected function getRouteParams(ServerRequestInterface $request): array { return $request->getAttribute('routeParameters'); } + + protected function dispatchLSCachePurgingEvent(): void + { + $purgeData = $this->cachePurger->getPurgeData(); + $this->events->dispatch(new LSCachePurging($purgeData)); + } } diff --git a/src/Middleware/PurgeCacheMiddleware.php b/src/Middleware/PurgeCacheMiddleware.php index 1f475bb..a50eb43 100644 --- a/src/Middleware/PurgeCacheMiddleware.php +++ b/src/Middleware/PurgeCacheMiddleware.php @@ -4,44 +4,19 @@ use ACPL\FlarumCache\LSCache; use Illuminate\Support\Str; -use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\RequestHandlerInterface; class PurgeCacheMiddleware extends AbstractPurgeCacheMiddleware { - protected function processPurge( - ServerRequestInterface $request, - RequestHandlerInterface $handler, - ResponseInterface $response, - ): ResponseInterface { - $purgeParams = $this->getPurgeParamsFromCachePurger(); - $purgeParams = array_merge($purgeParams, $this->getPurgeParamsForRoute($request)); - $this->cachePurger->clearPurgeData(); - - return $this->addPurgeParamsToResponse($response, array_unique($purgeParams)); - } - - private function getPurgeParamsFromCachePurger(): array - { - $purgeData = $this->cachePurger->getPurgeData(); - $paths = $purgeData['paths'] ?? []; - $tags = array_map(fn ($tag) => "tag=$tag", $purgeData['tags'] ?? []); - - return array_merge($paths, $tags); - } - - private function getPurgeParamsForRoute(ServerRequestInterface $request): array + protected function preparePurgeData(ServerRequestInterface $request): void { $routeName = $this->currentRouteName; $rootRouteName = LSCache::extractRootRouteName($routeName); $params = $this->getRouteParams($request); if (! empty($params['id']) && $this->shouldPurgeRoute($rootRouteName, $routeName)) { - return ["tag={$rootRouteName}_{$params['id']}"]; + $this->cachePurger->addPurgeTag("tag={$rootRouteName}_{$params['id']}"); } - - return []; } private function shouldPurgeRoute(string $rootRouteName, string $routeName): bool diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index 33b6a1c..9042b4a 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -3,10 +3,10 @@ namespace ACPL\FlarumCache\Utility; use ACPL\FlarumCache\Command\LSCacheClearCommand; -use Illuminate\Contracts\Queue\Queue; +use ACPL\FlarumCache\Event\LSCachePurging; +use Illuminate\Events\Dispatcher; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; - use const PHP_SAPI; /** @@ -15,14 +15,23 @@ */ class LSCachePurger { - private static array $purgeData = []; + /** + * @var array{ + * paths: string[], + * tags: string[] + * } $purgeData + */ + private static array $purgeData = [ + 'paths' => [], + 'tags' => [], + ]; /** * @var array|string[] */ public static array $resourcesSupportedByEvent = ['discussion', 'post', 'user']; - public function __construct(protected readonly LSCacheClearCommand $cacheClearCommand, protected Queue $queue) + public function __construct(protected readonly LSCacheClearCommand $cacheClearCommand, protected Dispatcher $events) { } @@ -59,7 +68,10 @@ public function getPurgeData(): array public function clearPurgeData(): void { - self::$purgeData = []; + self::$purgeData = [ + 'paths' => [], + 'tags' => [], + ]; } public function executePurge(): void @@ -78,6 +90,8 @@ private function purgeViaCli(): void { $input = []; + $this->events->dispatch(new LSCachePurging(self::$purgeData)); + if (! empty(self::$purgeData['paths'])) { $input['--path'] = self::$purgeData['paths']; } From 2148fd1c2d1180fff5718b747c688acca44e63fb Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 12 Sep 2024 20:51:29 +0000 Subject: [PATCH 20/38] Apply fixes from StyleCI --- src/Event/LSCachePurging.php | 4 +++- src/Middleware/AbstractPurgeCacheMiddleware.php | 1 + src/Utility/LSCachePurger.php | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Event/LSCachePurging.php b/src/Event/LSCachePurging.php index 14c84b1..12c3cdc 100644 --- a/src/Event/LSCachePurging.php +++ b/src/Event/LSCachePurging.php @@ -15,5 +15,7 @@ class LSCachePurging * tags: string[] * } $data */ - public function __construct(public array $data, public ?User $actor = null) { } + public function __construct(public array $data, public ?User $actor = null) + { + } } diff --git a/src/Middleware/AbstractPurgeCacheMiddleware.php b/src/Middleware/AbstractPurgeCacheMiddleware.php index fd6cd74..1c02357 100644 --- a/src/Middleware/AbstractPurgeCacheMiddleware.php +++ b/src/Middleware/AbstractPurgeCacheMiddleware.php @@ -72,6 +72,7 @@ protected function formatPurgeParams(array $purgeData): array array_map(fn (string $tag) => "tag=$tag", $purgeData['tags']), ); } + return $params; } diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index 9042b4a..1f19897 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -7,6 +7,7 @@ use Illuminate\Events\Dispatcher; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; + use const PHP_SAPI; /** From dbc1774fc808c17f74721fc4c67b341218da2cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:55:50 +0200 Subject: [PATCH 21/38] feat: add actor LSCachePurging event --- src/Middleware/AbstractPurgeCacheMiddleware.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Middleware/AbstractPurgeCacheMiddleware.php b/src/Middleware/AbstractPurgeCacheMiddleware.php index 1c02357..3442598 100644 --- a/src/Middleware/AbstractPurgeCacheMiddleware.php +++ b/src/Middleware/AbstractPurgeCacheMiddleware.php @@ -5,6 +5,7 @@ use ACPL\FlarumCache\Event\LSCachePurging; use ACPL\FlarumCache\LSCacheHeader; use ACPL\FlarumCache\Utility\LSCachePurger; +use Flarum\Http\RequestUtil; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Events\Dispatcher; use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; @@ -28,7 +29,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if ($this->shouldProcessPurge($request, $response)) { $this->preparePurgeData($request); - $this->dispatchLSCachePurgingEvent(); + $this->dispatchLSCachePurgingEvent($request); $response = $this->addPurgeParamsToResponse($response); } @@ -88,9 +89,9 @@ protected function getRouteParams(ServerRequestInterface $request): array return $request->getAttribute('routeParameters'); } - protected function dispatchLSCachePurgingEvent(): void + protected function dispatchLSCachePurgingEvent(ServerRequestInterface $request): void { $purgeData = $this->cachePurger->getPurgeData(); - $this->events->dispatch(new LSCachePurging($purgeData)); + $this->events->dispatch(new LSCachePurging($purgeData), RequestUtil::getActor($request)); } } From 1fea496fa824e8b3848187c269ef81c792610656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:01:25 +0200 Subject: [PATCH 22/38] style: group some imports --- extend.php | 39 +++++++++++-------- .../AbstractCacheTagsMiddleware.php | 6 +-- src/Middleware/CacheControlMiddleware.php | 6 +-- src/Middleware/LSTagsMiddlewareAbstract.php | 3 +- src/Middleware/LoginMiddleware.php | 7 +--- src/Middleware/LogoutMiddleware.php | 7 +--- src/Middleware/VaryCookieMiddleware.php | 9 ++--- src/Utility/LSCachePurger.php | 4 +- 8 files changed, 35 insertions(+), 46 deletions(-) diff --git a/extend.php b/extend.php index a4bccac..b96ed2b 100644 --- a/extend.php +++ b/extend.php @@ -11,24 +11,29 @@ namespace ACPL\FlarumCache; -use ACPL\FlarumCache\Api\Controller\LSCacheCsrfResponseController; -use ACPL\FlarumCache\Api\Controller\PurgeLSCacheController; +use ACPL\FlarumCache\Api\Controller\{LSCacheCsrfResponseController, PurgeLSCacheController}; use ACPL\FlarumCache\Command\LSCacheClearCommand; -use ACPL\FlarumCache\Compatibility\ClarkWinkelmann\AuthorChange\ClarkWinkelmannAuthorChangeEventSubscriber; -use ACPL\FlarumCache\Compatibility\Flarum\Likes\FlarumLikesEventSubscriber; -use ACPL\FlarumCache\Compatibility\Flarum\Tags\FlarumTagsEventSubscriber; -use ACPL\FlarumCache\Compatibility\FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware; -use ACPL\FlarumCache\Compatibility\v17development\FlarumBlog\FlarumBlogEventSubscriber; -use ACPL\FlarumCache\Listener\ClearingCacheListener; -use ACPL\FlarumCache\Listener\DiscussionEventSubscriber; -use ACPL\FlarumCache\Listener\PostEventSubscriber; -use ACPL\FlarumCache\Listener\UserEventSubscriber; -use ACPL\FlarumCache\Middleware\CacheControlMiddleware; -use ACPL\FlarumCache\Middleware\LoginMiddleware; -use ACPL\FlarumCache\Middleware\LogoutMiddleware; -use ACPL\FlarumCache\Middleware\LSTagsMiddlewareAbstract; -use ACPL\FlarumCache\Middleware\PurgeCacheMiddleware; -use ACPL\FlarumCache\Middleware\VaryCookieMiddleware; +use ACPL\FlarumCache\Compatibility\{ + ClarkWinkelmann\AuthorChange\ClarkWinkelmannAuthorChangeEventSubscriber, + Flarum\Likes\FlarumLikesEventSubscriber, + Flarum\Tags\FlarumTagsEventSubscriber, + FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware, + v17development\FlarumBlog\FlarumBlogEventSubscriber +}; +use ACPL\FlarumCache\Listener\{ + ClearingCacheListener, + DiscussionEventSubscriber, + PostEventSubscriber, + UserEventSubscriber +}; +use ACPL\FlarumCache\Middleware\{ + CacheControlMiddleware, + LoginMiddleware, + LogoutMiddleware, + LSTagsMiddlewareAbstract, + PurgeCacheMiddleware, + VaryCookieMiddleware +}; use Flarum\Extend; use Flarum\Foundation\Event\ClearingCache; use Flarum\Http\Middleware\CheckCsrfToken; diff --git a/src/Middleware/AbstractCacheTagsMiddleware.php b/src/Middleware/AbstractCacheTagsMiddleware.php index 3aac08e..9620820 100644 --- a/src/Middleware/AbstractCacheTagsMiddleware.php +++ b/src/Middleware/AbstractCacheTagsMiddleware.php @@ -3,10 +3,8 @@ namespace ACPL\FlarumCache\Middleware; use ACPL\FlarumCache\LSCacheHeader; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; +use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface}; abstract class AbstractCacheTagsMiddleware implements MiddlewareInterface { diff --git a/src/Middleware/CacheControlMiddleware.php b/src/Middleware/CacheControlMiddleware.php index 4cc3cd3..67afc4a 100644 --- a/src/Middleware/CacheControlMiddleware.php +++ b/src/Middleware/CacheControlMiddleware.php @@ -7,10 +7,8 @@ use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Support\Str; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; +use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface}; class CacheControlMiddleware implements MiddlewareInterface { diff --git a/src/Middleware/LSTagsMiddlewareAbstract.php b/src/Middleware/LSTagsMiddlewareAbstract.php index a0ee5ca..a41025b 100644 --- a/src/Middleware/LSTagsMiddlewareAbstract.php +++ b/src/Middleware/LSTagsMiddlewareAbstract.php @@ -3,8 +3,7 @@ namespace ACPL\FlarumCache\Middleware; use ACPL\FlarumCache\LSCache; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; use Psr\Http\Server\RequestHandlerInterface; class LSTagsMiddlewareAbstract extends AbstractCacheTagsMiddleware diff --git a/src/Middleware/LoginMiddleware.php b/src/Middleware/LoginMiddleware.php index 24478dc..ee8fc15 100644 --- a/src/Middleware/LoginMiddleware.php +++ b/src/Middleware/LoginMiddleware.php @@ -7,11 +7,8 @@ use Flarum\Http\CookieFactory; use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Contracts\Session\Session; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Message\{ResponseInterface, ResponseInterface as Response, ServerRequestInterface}; +use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface}; class LoginMiddleware implements MiddlewareInterface { diff --git a/src/Middleware/LogoutMiddleware.php b/src/Middleware/LogoutMiddleware.php index dabc203..e4ecba3 100644 --- a/src/Middleware/LogoutMiddleware.php +++ b/src/Middleware/LogoutMiddleware.php @@ -8,11 +8,8 @@ use Flarum\Http\CookieFactory; use Illuminate\Contracts\Session\Session; use Laminas\Diactoros\Response\RedirectResponse; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Message\{ResponseInterface, ResponseInterface as Response, ServerRequestInterface}; +use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface}; class LogoutMiddleware implements MiddlewareInterface { diff --git a/src/Middleware/VaryCookieMiddleware.php b/src/Middleware/VaryCookieMiddleware.php index 9d83827..e4f06a8 100644 --- a/src/Middleware/VaryCookieMiddleware.php +++ b/src/Middleware/VaryCookieMiddleware.php @@ -9,11 +9,8 @@ use Flarum\Http\RequestUtil; use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Contracts\Session\Session; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; +use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface}; class VaryCookieMiddleware implements MiddlewareInterface { @@ -46,7 +43,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $this->withVaryCookie($response, $session); } - private function withVaryCookie(Response $response, ?Session $session): Response + private function withVaryCookie(ResponseInterface $response, ?Session $session): ResponseInterface { if (! $session) { return $response; diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index 1f19897..36057ca 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -5,9 +5,7 @@ use ACPL\FlarumCache\Command\LSCacheClearCommand; use ACPL\FlarumCache\Event\LSCachePurging; use Illuminate\Events\Dispatcher; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\NullOutput; - +use Symfony\Component\Console\{Input\ArrayInput, Output\NullOutput}; use const PHP_SAPI; /** From 6ed78e281105ae2a6ff083f0955a540d9770d0ec Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 12 Sep 2024 21:01:38 +0000 Subject: [PATCH 23/38] Apply fixes from StyleCI --- extend.php | 2 +- src/Utility/LSCachePurger.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extend.php b/extend.php index b96ed2b..d677d9a 100644 --- a/extend.php +++ b/extend.php @@ -28,9 +28,9 @@ }; use ACPL\FlarumCache\Middleware\{ CacheControlMiddleware, + LSTagsMiddlewareAbstract, LoginMiddleware, LogoutMiddleware, - LSTagsMiddlewareAbstract, PurgeCacheMiddleware, VaryCookieMiddleware }; diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index 36057ca..3f8f311 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -6,6 +6,7 @@ use ACPL\FlarumCache\Event\LSCachePurging; use Illuminate\Events\Dispatcher; use Symfony\Component\Console\{Input\ArrayInput, Output\NullOutput}; + use const PHP_SAPI; /** From 7dea0ec1fa53f97d15ccb5a890b4962f363770f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:02:40 +0200 Subject: [PATCH 24/38] fix: LSTagsMiddleware name --- extend.php | 6 +++--- .../{LSTagsMiddlewareAbstract.php => LSTagsMiddleware.php} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/Middleware/{LSTagsMiddlewareAbstract.php => LSTagsMiddleware.php} (95%) diff --git a/extend.php b/extend.php index d677d9a..cfe2edd 100644 --- a/extend.php +++ b/extend.php @@ -28,7 +28,7 @@ }; use ACPL\FlarumCache\Middleware\{ CacheControlMiddleware, - LSTagsMiddlewareAbstract, + LSTagsMiddleware, LoginMiddleware, LogoutMiddleware, PurgeCacheMiddleware, @@ -62,8 +62,8 @@ (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, LogoutMiddleware::class), // Tag routes - (new Extend\Middleware('forum'))->add(LSTagsMiddlewareAbstract::class), - (new Extend\Middleware('api'))->add(LSTagsMiddlewareAbstract::class), + (new Extend\Middleware('forum'))->add(LSTagsMiddleware::class), + (new Extend\Middleware('api'))->add(LSTagsMiddleware::class), // Cache routes (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, CacheControlMiddleware::class), diff --git a/src/Middleware/LSTagsMiddlewareAbstract.php b/src/Middleware/LSTagsMiddleware.php similarity index 95% rename from src/Middleware/LSTagsMiddlewareAbstract.php rename to src/Middleware/LSTagsMiddleware.php index a41025b..4cddd3e 100644 --- a/src/Middleware/LSTagsMiddlewareAbstract.php +++ b/src/Middleware/LSTagsMiddleware.php @@ -6,7 +6,7 @@ use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; use Psr\Http\Server\RequestHandlerInterface; -class LSTagsMiddlewareAbstract extends AbstractCacheTagsMiddleware +class LSTagsMiddleware extends AbstractCacheTagsMiddleware { protected function processTags( ServerRequestInterface $request, From 11d31ea57204735eb4c8416d51a065161f0d441c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:06:27 +0200 Subject: [PATCH 25/38] refactor: update extension namespace --- composer.json | 2 +- extend.php | 12 ++++++------ migrations/2023_05_16_000001_update_htaccess.php | 4 ++-- src/Api/Controller/LSCacheCsrfResponseController.php | 2 +- src/Api/Controller/PurgeLSCacheController.php | 4 ++-- src/Command/LSCacheClearCommand.php | 2 +- .../ClarkWinkelmannAuthorChangeEventSubscriber.php | 4 ++-- .../Flarum/Likes/FlarumLikesEventSubscriber.php | 4 ++-- .../Flarum/Tags/FlarumTagsEventSubscriber.php | 4 ++-- .../Masquerade/FofMasqueradePurgeCacheMiddleware.php | 4 ++-- .../FlarumBlog/FlarumBlogEventSubscriber.php | 6 +++--- src/Event/LSCachePurging.php | 2 +- src/LSCache.php | 2 +- src/LSCacheHeader.php | 2 +- src/Listener/AbstractCachePurgeListener.php | 4 ++-- src/Listener/AbstractCachePurgeSubscriber.php | 4 ++-- src/Listener/ClearingCacheListener.php | 4 ++-- src/Listener/DiscussionEventSubscriber.php | 2 +- src/Listener/PostEventSubscriber.php | 2 +- src/Listener/UpdateSettingsListener.php | 6 +++--- src/Listener/UserEventSubscriber.php | 2 +- src/Middleware/AbstractCacheTagsMiddleware.php | 4 ++-- src/Middleware/AbstractPurgeCacheMiddleware.php | 8 ++++---- src/Middleware/CacheControlMiddleware.php | 4 ++-- src/Middleware/LSTagsMiddleware.php | 4 ++-- src/Middleware/LoginMiddleware.php | 4 ++-- src/Middleware/LogoutMiddleware.php | 6 +++--- src/Middleware/PurgeCacheMiddleware.php | 4 ++-- src/Middleware/VaryCookieMiddleware.php | 6 +++--- src/Utility/HtaccessManager.php | 8 ++++---- src/Utility/LSCachePurger.php | 6 +++--- 31 files changed, 66 insertions(+), 66 deletions(-) diff --git a/composer.json b/composer.json index 6dd4107..0c2c670 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ ], "autoload": { "psr-4": { - "ACPL\\FlarumCache\\": "src/" + "ACPL\\FlarumLSCache\\": "src/" } }, "extra": { diff --git a/extend.php b/extend.php index cfe2edd..ff6d447 100644 --- a/extend.php +++ b/extend.php @@ -9,24 +9,24 @@ * file that was distributed with this source code. */ -namespace ACPL\FlarumCache; +namespace ACPL\FlarumLSCache; -use ACPL\FlarumCache\Api\Controller\{LSCacheCsrfResponseController, PurgeLSCacheController}; -use ACPL\FlarumCache\Command\LSCacheClearCommand; -use ACPL\FlarumCache\Compatibility\{ +use ACPL\FlarumLSCache\Api\Controller\{LSCacheCsrfResponseController, PurgeLSCacheController}; +use ACPL\FlarumLSCache\Command\LSCacheClearCommand; +use ACPL\FlarumLSCache\Compatibility\{ ClarkWinkelmann\AuthorChange\ClarkWinkelmannAuthorChangeEventSubscriber, Flarum\Likes\FlarumLikesEventSubscriber, Flarum\Tags\FlarumTagsEventSubscriber, FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware, v17development\FlarumBlog\FlarumBlogEventSubscriber }; -use ACPL\FlarumCache\Listener\{ +use ACPL\FlarumLSCache\Listener\{ ClearingCacheListener, DiscussionEventSubscriber, PostEventSubscriber, UserEventSubscriber }; -use ACPL\FlarumCache\Middleware\{ +use ACPL\FlarumLSCache\Middleware\{ CacheControlMiddleware, LSTagsMiddleware, LoginMiddleware, diff --git a/migrations/2023_05_16_000001_update_htaccess.php b/migrations/2023_05_16_000001_update_htaccess.php index 5cc8d33..4a34517 100644 --- a/migrations/2023_05_16_000001_update_htaccess.php +++ b/migrations/2023_05_16_000001_update_htaccess.php @@ -1,6 +1,6 @@ function () { $htaccessManager = lsCacheGetHtaccessManager(); $htaccessManager->removeLsCacheBlock(); - } + }, ]; diff --git a/src/Api/Controller/LSCacheCsrfResponseController.php b/src/Api/Controller/LSCacheCsrfResponseController.php index 75d3c96..325f5a2 100644 --- a/src/Api/Controller/LSCacheCsrfResponseController.php +++ b/src/Api/Controller/LSCacheCsrfResponseController.php @@ -1,6 +1,6 @@ cookie->getName(LSCache::VARY_COOKIE), $this->cookie->getName('remember'), - 'locale' - ]).'"]' + 'locale', + ]).'"]', ); // In the extend.php, there is an extender for default settings, diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index 3f8f311..bdf28ff 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -1,9 +1,9 @@ Date: Thu, 12 Sep 2024 23:35:45 +0200 Subject: [PATCH 26/38] refactor: add support for sycho/flarum-move-posts --- composer.json | 7 +++- extend.php | 4 ++ .../MovePosts/SychOMovePostsSubscriber.php | 37 +++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php diff --git a/composer.json b/composer.json index 0c2c670..04ab8fd 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,8 @@ "flarum/approval": "^1.8", "flarum/likes": "^1.8", "fof/masquerade": "^2.1", - "clarkwinkelmann/flarum-ext-author-change": "^1.0" + "clarkwinkelmann/flarum-ext-author-change": "^1.0", + "sycho/flarum-move-posts": "^0.1.7" }, "suggest": { "blomstra/flarum-redis": "This library allows using Redis as cache, session and for the queue. https://github.com/blomstra/flarum-redis#set-up" @@ -62,7 +63,9 @@ "flarum/tags", "flarum/likes", "fof/masquerade", - "v17development/flarum-blog" + "v17development/flarum-blog", + "clarkwinkelmann/flarum-ext-author-change", + "sycho/flarum-move-posts" ] }, "flarum-cli": { diff --git a/extend.php b/extend.php index ff6d447..29ebebc 100644 --- a/extend.php +++ b/extend.php @@ -18,6 +18,7 @@ Flarum\Likes\FlarumLikesEventSubscriber, Flarum\Tags\FlarumTagsEventSubscriber, FriendsOfFlarum\Masquerade\FofMasqueradePurgeCacheMiddleware, + SychO\MovePosts\SychOMovePostsSubscriber, v17development\FlarumBlog\FlarumBlogEventSubscriber }; use ACPL\FlarumLSCache\Listener\{ @@ -101,5 +102,8 @@ ]) ->whenExtensionEnabled('clarkwinkelmann-author-change', [ (new Extend\Event)->subscribe(ClarkWinkelmannAuthorChangeEventSubscriber::class), + ]) + ->whenExtensionEnabled('sycho-move-posts', [ + (new Extend\Event)->subscribe(SychOMovePostsSubscriber::class), ]), ]; diff --git a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php new file mode 100644 index 0000000..4b4c8f1 --- /dev/null +++ b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php @@ -0,0 +1,37 @@ +addPurgeListener($events, PostsMoved::class, [$this, 'handlePostsMoved']); + } + + protected function handlePostsMoved(PostsMoved $event): void + { + $postUserTags = []; + $event->posts->each(function ($post) use (&$postUserTags) { + /** @var CommentPost $post */ + $postUserTags[] = "user_{$post->user->id}"; + $postUserTags[] = "user_{$post->user->username}"; + }); + + $this->purger->addPurgeTags([ + 'default', + 'index', + 'posts.index', + 'discussions.index', + "discussion_{$event->sourceDiscussion->id}", + "discussion_{$event->targetDiscussion->id}", + ...array_map(fn ($postId) => "post_$postId", $event->posts->pluck('id')->toArray()), + ...$postUserTags, + ]); + } +} From e79ebd980daf81a1f375a9f6d9f200020ee4917d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:37:57 +0200 Subject: [PATCH 27/38] refactor: simplify code --- .../SychO/MovePosts/SychOMovePostsSubscriber.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php index 4b4c8f1..45bfb1b 100644 --- a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php +++ b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php @@ -16,11 +16,12 @@ public function subscribe(Dispatcher $events): void protected function handlePostsMoved(PostsMoved $event): void { - $postUserTags = []; - $event->posts->each(function ($post) use (&$postUserTags) { + $cacheTags = []; + $event->posts->each(function ($post) use (&$cacheTags) { /** @var CommentPost $post */ - $postUserTags[] = "user_{$post->user->id}"; - $postUserTags[] = "user_{$post->user->username}"; + $cacheTags[] = "post_{$post->id}"; + $cacheTags[] = "user_{$post->user->id}"; + $cacheTags[] = "user_{$post->user->username}"; }); $this->purger->addPurgeTags([ @@ -30,8 +31,7 @@ protected function handlePostsMoved(PostsMoved $event): void 'discussions.index', "discussion_{$event->sourceDiscussion->id}", "discussion_{$event->targetDiscussion->id}", - ...array_map(fn ($postId) => "post_$postId", $event->posts->pluck('id')->toArray()), - ...$postUserTags, + ...$cacheTags, ]); } } From b85687008b9b1ae437d320c1d9566aaf17e56cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:23:14 +0200 Subject: [PATCH 28/38] chore: ignore some external PHPStan errors --- src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php | 3 +++ .../v17development/FlarumBlog/FlarumBlogEventSubscriber.php | 1 + src/Listener/DiscussionEventSubscriber.php | 3 ++- src/Listener/PostEventSubscriber.php | 3 ++- src/Listener/UserEventSubscriber.php | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php index d957d8a..5eb7ebf 100644 --- a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php +++ b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php @@ -56,6 +56,7 @@ public function handleDiscussionEvents( ): void { if ( ($event instanceof DiscussionDeleted && $event->discussion->hidden_at !== null) + /** @phpstan-ignore-next-line Access to an undefined property Flarum\Discussion\Discussion::$is_approved. */ || $event->discussion->is_approved === false ) { return; @@ -71,6 +72,7 @@ public function handlePostEvents(PostDeleted|PostHidden|Posted|PostRestored $eve { if ( ($event instanceof PostRestored && $event->post->discussion->hidden_at !== null) + /** @phpstan-ignore-next-line Access to an undefined property Flarum\Discussion\Discussion::$is_approved. */ || $event->post->discussion->is_approved === false ) { return; @@ -84,6 +86,7 @@ public function handlePostEvents(PostDeleted|PostHidden|Posted|PostRestored $eve protected function generateCacheTagsForDiscussionTags(Discussion $discussion): array { + /** @phpstan-ignore-next-line Access to an undefined property Flarum\Discussion\Discussion::$is_approved. */ return $discussion->tags->map(fn (Tag $tag) => "tag_$tag->slug")->toArray(); } } diff --git a/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php b/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php index f71c3e9..611bdb2 100644 --- a/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php +++ b/src/Compatibility/v17development/FlarumBlog/FlarumBlogEventSubscriber.php @@ -20,6 +20,7 @@ public function handle(BlogMetaSaving $event): void { $this->purger->addPurgeTags([ 'blog.overview', + /** @phpstan-ignore-next-line Access to an undefined property V17Development\FlarumBlog\BlogMeta\BlogMeta::$discussion_id. */ "blog_{$event->blogMeta->discussion_id}", ]); } diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index 9abb2f6..b548928 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -50,7 +50,8 @@ protected function shouldPurge( ): bool { return ! ( $event->discussion->is_private - || $event->discussion?->is_approved === false + /** @phpstan-ignore-next-line Access to an undefined property Flarum\Discussion\Discussion::$is_approved. */ + || $event->discussion->is_approved === false ); } } diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index 5a9c834..2e33d03 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -58,7 +58,8 @@ protected function shouldPurge(Deleted|Hidden|Posted|Restored|Revised|PostWasApp { return ! ( $event->post->discussion->is_private - || $event->post?->is_approved === false + /** @phpstan-ignore-next-line Access to an undefined property Flarum\Post\Post::$is_approved. */ + || $event->post->is_approved === false ); } } diff --git a/src/Listener/UserEventSubscriber.php b/src/Listener/UserEventSubscriber.php index 6f80604..4aa0eed 100644 --- a/src/Listener/UserEventSubscriber.php +++ b/src/Listener/UserEventSubscriber.php @@ -22,6 +22,7 @@ public function subscribe(Dispatcher $events): void public function handleUserWithPosts(AvatarChanged|GroupsChanged|Renamed $event): void { // TODO: If user has a lot discussion chunk it and push to the queue job + /** @phpstan-ignore-next-line Call to an undefined method Illuminate\Database\Eloquent\Relations\Relation::pluck(). */ $discussions = $event->user->posts()->getRelation('discussion')->pluck('id')->toArray(); $this->purger->addPurgeTags([ From 34858e0eaf31fb29f767a90af37d1ddb8bb9e0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:12:15 +0200 Subject: [PATCH 29/38] feat: purge list from settings --- locale/en.yml | 4 +- src/Listener/AbstractCachePurgeListener.php | 3 +- src/Listener/AbstractCachePurgeSubscriber.php | 3 +- src/Listener/DiscussionCachePurgeTrait.php | 37 +++++++++++++++++++ src/Listener/DiscussionEventSubscriber.php | 12 ++---- src/Listener/PostEventSubscriber.php | 12 ++---- 6 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 src/Listener/DiscussionCachePurgeTrait.php diff --git a/locale/en.yml b/locale/en.yml index 7760c5f..ad236c0 100644 --- a/locale/en.yml +++ b/locale/en.yml @@ -11,8 +11,8 @@ acpl-lscache: serve_stale_label: "Serve Stale Content" serve_stale_help: "If enabled, an outdated version of a cached page will be served to visitors until a fresh cache copy is generated. This reduces server load. If disabled, the page will be dynamically generated during the cache update, which may increase wait times. By design, this option can serve out-of-date content. Please do not enable this if you find that unacceptable." - purge_on_discussion_update_label: "Purge URLs or Tags on Discussion or Post Update" - purge_on_discussion_update_help: "Enter the URLs or Tags you want to purge when a discussion or post is updated, one per line. URL should start with /, e.g. /rankings, and cache Tag should start with tag=, e.g. tag=rankings. For multiple routes, adding a rule in .htaccess with a regular expression that tags routes and entering only this tag here is faster. Learn more. By default, the cache for the homepage and updated discussions is purged." + purge_on_discussion_update_label: "Purge URLs or cache Tags on Discussion Update" + purge_on_discussion_update_help: "Enter the URLs or cache Tags you want to purge when a discussion is updated, one per line. URL should start with /, e.g. /rankings, and cache Tag should start with tag=, e.g. tag=rankings. For multiple routes, adding a rule in .htaccess with a regular expression that tags routes and entering only this tag here is faster. Learn more. By default, the cache for the homepage and updated discussions is purged." cache_exclude_label: "Exclude Paths from Caching" cache_exclude_help: "Paths containing these strings will not be cached. For /mypath/mypage?aa=bb, you can use mypage?aa=. To match the beginning, add ^ at the start. For an exact match, add $ at the end of the URL. One per line." diff --git a/src/Listener/AbstractCachePurgeListener.php b/src/Listener/AbstractCachePurgeListener.php index 0f0d948..bc7287e 100644 --- a/src/Listener/AbstractCachePurgeListener.php +++ b/src/Listener/AbstractCachePurgeListener.php @@ -3,11 +3,12 @@ namespace ACPL\FlarumLSCache\Listener; use ACPL\FlarumLSCache\Utility\LSCachePurger; +use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Events\Dispatcher; abstract class AbstractCachePurgeListener { - public function __construct(protected LSCachePurger $purger) + public function __construct(protected LSCachePurger $purger, protected SettingsRepositoryInterface $settings) { } diff --git a/src/Listener/AbstractCachePurgeSubscriber.php b/src/Listener/AbstractCachePurgeSubscriber.php index 82381b3..0373d85 100644 --- a/src/Listener/AbstractCachePurgeSubscriber.php +++ b/src/Listener/AbstractCachePurgeSubscriber.php @@ -3,11 +3,12 @@ namespace ACPL\FlarumLSCache\Listener; use ACPL\FlarumLSCache\Utility\LSCachePurger; +use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Events\Dispatcher; abstract class AbstractCachePurgeSubscriber { - public function __construct(protected LSCachePurger $purger) + public function __construct(protected LSCachePurger $purger, protected SettingsRepositoryInterface $settings) { } diff --git a/src/Listener/DiscussionCachePurgeTrait.php b/src/Listener/DiscussionCachePurgeTrait.php new file mode 100644 index 0000000..e8d09ef --- /dev/null +++ b/src/Listener/DiscussionCachePurgeTrait.php @@ -0,0 +1,37 @@ +purger->addPurgeTags([ + 'default', + 'index', + 'discussions.index', + ]); + + $purgeList = $this->settings->get('acpl-lscache.purge_on_discussion_update'); + if (! empty($purgeList)) { + $purgeList = explode("\n", $purgeList); + + $paths = Arr::where($purgeList, fn ($item) => str_starts_with($item, '/')); + if (! empty($paths)) { + $this->purger->addPurgePaths($paths); + } + + $tags = Arr::where($purgeList, fn ($item) => str_starts_with($item, 'tag=')); + if (! empty($tags)) { + $this->purger->addPurgeTags($tags); + } + } + } +} diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index b548928..f73b1dd 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -2,15 +2,13 @@ namespace ACPL\FlarumLSCache\Listener; -use Flarum\Discussion\Event\Deleted; -use Flarum\Discussion\Event\Hidden; -use Flarum\Discussion\Event\Renamed; -use Flarum\Discussion\Event\Restored; -use Flarum\Discussion\Event\Started; +use Flarum\Discussion\Event\{Deleted, Hidden, Renamed, Restored, Started}; use Illuminate\Contracts\Events\Dispatcher; class DiscussionEventSubscriber extends AbstractCachePurgeSubscriber { + use DiscussionCachePurgeTrait; + public function subscribe(Dispatcher $events): void { $shared = [Hidden::class, Started::class, Restored::class, Renamed::class]; @@ -27,10 +25,8 @@ protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void return; } + $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'default', - 'index', - 'discussions.index', "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index 2e33d03..e79d46e 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -3,15 +3,13 @@ namespace ACPL\FlarumLSCache\Listener; use Flarum\Approval\Event\PostWasApproved; -use Flarum\Post\Event\Deleted; -use Flarum\Post\Event\Hidden; -use Flarum\Post\Event\Posted; -use Flarum\Post\Event\Restored; -use Flarum\Post\Event\Revised; +use Flarum\Post\Event\{Deleted, Hidden, Posted, Restored, Revised}; use Illuminate\Contracts\Events\Dispatcher; class PostEventSubscriber extends AbstractCachePurgeSubscriber { + use DiscussionCachePurgeTrait; + public function subscribe(Dispatcher $events): void { $shared = [Hidden::class, Posted::class, Restored::class, PostWasApproved::class]; @@ -28,11 +26,9 @@ protected function handle(Hidden|Posted|Restored|PostWasApproved $event): void return; } + $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'default', - 'index', 'posts.index', - 'discussions.index', "discussion_{$event->post->discussion_id}", "user_{$event->post->user_id}", "user_{$event->post->user_id}", From 241bf46b8057204ac9fcfe7a5845b272669fcda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:14:58 +0200 Subject: [PATCH 30/38] style: cleanup code --- src/Listener/ClearingCacheListener.php | 7 ------- src/Listener/UserEventSubscriber.php | 7 ++----- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Listener/ClearingCacheListener.php b/src/Listener/ClearingCacheListener.php index b1ee376..089ce71 100644 --- a/src/Listener/ClearingCacheListener.php +++ b/src/Listener/ClearingCacheListener.php @@ -2,17 +2,10 @@ namespace ACPL\FlarumLSCache\Listener; -use ACPL\FlarumLSCache\Utility\LSCachePurger; -use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Events\Dispatcher; class ClearingCacheListener extends AbstractCachePurgeListener { - public function __construct(protected LSCachePurger $purger, protected SettingsRepositoryInterface $settings) - { - parent::__construct($this->purger); - } - protected function addPurgeData(Dispatcher $event): void { if ($this->settings->get('acpl-lscache.clearing_cache_listener')) { diff --git a/src/Listener/UserEventSubscriber.php b/src/Listener/UserEventSubscriber.php index 4aa0eed..2f800ed 100644 --- a/src/Listener/UserEventSubscriber.php +++ b/src/Listener/UserEventSubscriber.php @@ -2,10 +2,7 @@ namespace ACPL\FlarumLSCache\Listener; -use Flarum\User\Event\AvatarChanged; -use Flarum\User\Event\Deleted; -use Flarum\User\Event\GroupsChanged; -use Flarum\User\Event\Renamed; +use Flarum\User\Event\{AvatarChanged, Deleted, GroupsChanged, Renamed}; use Illuminate\Contracts\Events\Dispatcher; class UserEventSubscriber extends AbstractCachePurgeSubscriber @@ -18,7 +15,7 @@ public function subscribe(Dispatcher $events): void } } - /** Purge discussions where user has posted, so new user data is visible there */ + /** Purge discussions where user has posted. */ public function handleUserWithPosts(AvatarChanged|GroupsChanged|Renamed $event): void { // TODO: If user has a lot discussion chunk it and push to the queue job From ae99a271163e48a87ea5579420627952096ceaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:27:52 +0200 Subject: [PATCH 31/38] feat: use purge list settings in all discussion related subscribers --- ...kWinkelmannAuthorChangeEventSubscriber.php | 7 +++--- .../Likes/FlarumLikesEventSubscriber.php | 3 +-- .../Flarum/Tags/FlarumTagsEventSubscriber.php | 24 +++++++++---------- .../MovePosts/SychOMovePostsSubscriber.php | 7 +++--- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php index c07db10..3805ef9 100644 --- a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php +++ b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php @@ -3,6 +3,7 @@ namespace ACPL\FlarumLSCache\Compatibility\ClarkWinkelmann\AuthorChange; use ACPL\FlarumLSCache\Listener\AbstractCachePurgeSubscriber; +use ACPL\FlarumLSCache\Listener\DiscussionCachePurgeTrait; use ClarkWinkelmann\AuthorChange\Event\DiscussionCreateDateChanged; use ClarkWinkelmann\AuthorChange\Event\DiscussionUserChanged; use ClarkWinkelmann\AuthorChange\Event\PostCreateDateChanged; @@ -12,6 +13,8 @@ class ClarkWinkelmannAuthorChangeEventSubscriber extends AbstractCachePurgeSubscriber { + use DiscussionCachePurgeTrait; + public function subscribe(Dispatcher $events): void { $this->addPurgeListener($events, DiscussionCreateDateChanged::class, [$this, 'handleDiscussion']); @@ -23,10 +26,8 @@ public function subscribe(Dispatcher $events): void protected function handleDiscussion(DiscussionCreateDateChanged|DiscussionUserChanged $event): void { + $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'default', - 'index', - 'discussions.index', "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", diff --git a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php index 0277955..6ebb682 100644 --- a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php +++ b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php @@ -3,8 +3,7 @@ namespace ACPL\FlarumLSCache\Compatibility\Flarum\Likes; use ACPL\FlarumLSCache\Listener\AbstractCachePurgeSubscriber; -use Flarum\Likes\Event\PostWasLiked; -use Flarum\Likes\Event\PostWasUnliked; +use Flarum\Likes\Event\{PostWasLiked, PostWasUnliked}; use Illuminate\Contracts\Events\Dispatcher; class FlarumLikesEventSubscriber extends AbstractCachePurgeSubscriber diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php index 5eb7ebf..9bee7cf 100644 --- a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php +++ b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php @@ -2,23 +2,23 @@ namespace ACPL\FlarumLSCache\Compatibility\Flarum\Tags; -use ACPL\FlarumLSCache\Listener\AbstractCachePurgeSubscriber; +use ACPL\FlarumLSCache\Listener\{AbstractCachePurgeSubscriber, DiscussionCachePurgeTrait}; use Flarum\Discussion\Discussion; -use Flarum\Discussion\Event\Deleted as DiscussionDeleted; -use Flarum\Discussion\Event\Hidden as DiscussionHidden; -use Flarum\Discussion\Event\Renamed as DiscussionRenamed; -use Flarum\Discussion\Event\Restored as DiscussionRestored; -use Flarum\Discussion\Event\Started as DiscussionStarted; -use Flarum\Post\Event\Deleted as PostDeleted; -use Flarum\Post\Event\Hidden as PostHidden; -use Flarum\Post\Event\Posted; -use Flarum\Post\Event\Restored as PostRestored; +use Flarum\Discussion\Event\{Deleted as DiscussionDeleted, + Hidden as DiscussionHidden, + Renamed as DiscussionRenamed, + Restored as DiscussionRestored, + Started as DiscussionStarted +}; +use Flarum\Post\Event\{Deleted as PostDeleted, Hidden as PostHidden, Posted, Restored as PostRestored}; use Flarum\Tags\Event\DiscussionWasTagged; use Flarum\Tags\Tag; use Illuminate\Contracts\Events\Dispatcher; class FlarumTagsEventSubscriber extends AbstractCachePurgeSubscriber { + use DiscussionCachePurgeTrait; + public function subscribe(Dispatcher $events): void { $this->addPurgeListener($events, DiscussionWasTagged::class, [$this, 'handleDiscussionWasTagged']); @@ -39,10 +39,8 @@ public function subscribe(Dispatcher $events): void public function handleDiscussionWasTagged(DiscussionWasTagged $event): void { + $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'default', - 'index', - 'discussions.index', "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", diff --git a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php index 45bfb1b..3f3117f 100644 --- a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php +++ b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php @@ -3,12 +3,15 @@ namespace ACPL\FlarumLSCache\Compatibility\SychO\MovePosts; use ACPL\FlarumLSCache\Listener\AbstractCachePurgeSubscriber; +use ACPL\FlarumLSCache\Listener\DiscussionCachePurgeTrait; use Flarum\Post\CommentPost; use Illuminate\Contracts\Events\Dispatcher; use SychO\MovePosts\Event\PostsMoved; class SychOMovePostsSubscriber extends AbstractCachePurgeSubscriber { + use DiscussionCachePurgeTrait; + public function subscribe(Dispatcher $events): void { $this->addPurgeListener($events, PostsMoved::class, [$this, 'handlePostsMoved']); @@ -24,11 +27,9 @@ protected function handlePostsMoved(PostsMoved $event): void $cacheTags[] = "user_{$post->user->username}"; }); + $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'default', - 'index', 'posts.index', - 'discussions.index', "discussion_{$event->sourceDiscussion->id}", "discussion_{$event->targetDiscussion->id}", ...$cacheTags, From 6d40489ec2288108598c3039f8de1d6d73a128b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:29:27 +0200 Subject: [PATCH 32/38] style: organize imports --- ...ClarkWinkelmannAuthorChangeEventSubscriber.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php index 3805ef9..17c5d14 100644 --- a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php +++ b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php @@ -2,13 +2,14 @@ namespace ACPL\FlarumLSCache\Compatibility\ClarkWinkelmann\AuthorChange; -use ACPL\FlarumLSCache\Listener\AbstractCachePurgeSubscriber; -use ACPL\FlarumLSCache\Listener\DiscussionCachePurgeTrait; -use ClarkWinkelmann\AuthorChange\Event\DiscussionCreateDateChanged; -use ClarkWinkelmann\AuthorChange\Event\DiscussionUserChanged; -use ClarkWinkelmann\AuthorChange\Event\PostCreateDateChanged; -use ClarkWinkelmann\AuthorChange\Event\PostEditDateChanged; -use ClarkWinkelmann\AuthorChange\Event\PostUserChanged; +use ACPL\FlarumLSCache\Listener\{AbstractCachePurgeSubscriber, DiscussionCachePurgeTrait}; +use ClarkWinkelmann\AuthorChange\Event\{ + DiscussionCreateDateChanged, + DiscussionUserChanged, + PostCreateDateChanged, + PostEditDateChanged, + PostUserChanged +}; use Illuminate\Contracts\Events\Dispatcher; class ClarkWinkelmannAuthorChangeEventSubscriber extends AbstractCachePurgeSubscriber From 7b59477e57cccc5c6f60a2adf26d9604abecf8d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 14 Sep 2024 00:39:35 +0200 Subject: [PATCH 33/38] feat: push purge command to queue --- extend.php | 4 +-- ...earCommand.php => LSCachePurgeCommand.php} | 2 +- src/Job/PurgeCacheViaCliJob.php | 34 +++++++++++++++++++ src/Listener/AbstractCachePurgeListener.php | 5 ++- src/Listener/AbstractCachePurgeSubscriber.php | 7 +++- src/Listener/ClearingCacheListener.php | 5 +-- src/Utility/LSCachePurger.php | 33 +++++------------- 7 files changed, 56 insertions(+), 34 deletions(-) rename src/Command/{LSCacheClearCommand.php => LSCachePurgeCommand.php} (97%) create mode 100644 src/Job/PurgeCacheViaCliJob.php diff --git a/extend.php b/extend.php index 29ebebc..f10ff07 100644 --- a/extend.php +++ b/extend.php @@ -12,7 +12,7 @@ namespace ACPL\FlarumLSCache; use ACPL\FlarumLSCache\Api\Controller\{LSCacheCsrfResponseController, PurgeLSCacheController}; -use ACPL\FlarumLSCache\Command\LSCacheClearCommand; +use ACPL\FlarumLSCache\Command\LSCachePurgeCommand; use ACPL\FlarumLSCache\Compatibility\{ ClarkWinkelmann\AuthorChange\ClarkWinkelmannAuthorChangeEventSubscriber, Flarum\Likes\FlarumLikesEventSubscriber, @@ -80,7 +80,7 @@ // Purge cache (new Extend\Routes('api'))->get('/lscache-purge', 'lscache.purge', PurgeLSCacheController::class), - (new Extend\Console)->command(LSCacheClearCommand::class), + (new Extend\Console)->command(LSCachePurgeCommand::class), (new Extend\Event)->listen(ClearingCache::class, ClearingCacheListener::class), (new Extend\Event)->subscribe(DiscussionEventSubscriber::class), diff --git a/src/Command/LSCacheClearCommand.php b/src/Command/LSCachePurgeCommand.php similarity index 97% rename from src/Command/LSCacheClearCommand.php rename to src/Command/LSCachePurgeCommand.php index 498f89b..f69f867 100644 --- a/src/Command/LSCacheClearCommand.php +++ b/src/Command/LSCachePurgeCommand.php @@ -10,7 +10,7 @@ use GuzzleHttp\Exception\GuzzleException; use Symfony\Component\Console\Input\InputOption; -class LSCacheClearCommand extends AbstractCommand +class LSCachePurgeCommand extends AbstractCommand { protected UrlGenerator $url; private SettingsRepositoryInterface $settings; diff --git a/src/Job/PurgeCacheViaCliJob.php b/src/Job/PurgeCacheViaCliJob.php new file mode 100644 index 0000000..dbba02a --- /dev/null +++ b/src/Job/PurgeCacheViaCliJob.php @@ -0,0 +1,34 @@ + [], 'tags' => []]) { } + + public function handle(LSCachePurgeCommand $command): void + { + $input = []; + + if (! empty($this->data['paths'])) { + $input['--path'] = $this->data['paths']; + } + + if (! empty($this->data['tags'])) { + $input['--tag'] = $this->data['tags']; + } + + $command->run(new ArrayInput($input), new NullOutput()); + } +} diff --git a/src/Listener/AbstractCachePurgeListener.php b/src/Listener/AbstractCachePurgeListener.php index bc7287e..16e0d75 100644 --- a/src/Listener/AbstractCachePurgeListener.php +++ b/src/Listener/AbstractCachePurgeListener.php @@ -4,7 +4,6 @@ use ACPL\FlarumLSCache\Utility\LSCachePurger; use Flarum\Settings\SettingsRepositoryInterface; -use Illuminate\Contracts\Events\Dispatcher; abstract class AbstractCachePurgeListener { @@ -12,11 +11,11 @@ public function __construct(protected LSCachePurger $purger, protected SettingsR { } - protected function handle(Dispatcher $event): void + public function handle($event): void { $this->addPurgeData($event); $this->purger->executePurge(); } - abstract protected function addPurgeData(Dispatcher $event): void; + abstract protected function addPurgeData($event): void; } diff --git a/src/Listener/AbstractCachePurgeSubscriber.php b/src/Listener/AbstractCachePurgeSubscriber.php index 0373d85..d14df5c 100644 --- a/src/Listener/AbstractCachePurgeSubscriber.php +++ b/src/Listener/AbstractCachePurgeSubscriber.php @@ -2,6 +2,7 @@ namespace ACPL\FlarumLSCache\Listener; +use ACPL\FlarumLSCache\Event\LSCachePurging; use ACPL\FlarumLSCache\Utility\LSCachePurger; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Events\Dispatcher; @@ -18,7 +19,11 @@ protected function addPurgeListener(Dispatcher $events, string $event, callable { $events->listen($event, function ($eventInstance) use ($handler) { $handler($eventInstance); - $this->purger->executePurge(); + + // Prevent infinite loop when something listens to LSCachePurging event + if (! $eventInstance instanceof LSCachePurging) { + $this->purger->executePurge(); + } }); } } diff --git a/src/Listener/ClearingCacheListener.php b/src/Listener/ClearingCacheListener.php index 089ce71..dd2d00e 100644 --- a/src/Listener/ClearingCacheListener.php +++ b/src/Listener/ClearingCacheListener.php @@ -2,11 +2,12 @@ namespace ACPL\FlarumLSCache\Listener; -use Illuminate\Contracts\Events\Dispatcher; +use Flarum\Foundation\Event\ClearingCache; class ClearingCacheListener extends AbstractCachePurgeListener { - protected function addPurgeData(Dispatcher $event): void + /** @param ClearingCache $event */ + protected function addPurgeData($event): void { if ($this->settings->get('acpl-lscache.clearing_cache_listener')) { $this->purger->addPurgePath('*'); diff --git a/src/Utility/LSCachePurger.php b/src/Utility/LSCachePurger.php index bdf28ff..6811458 100644 --- a/src/Utility/LSCachePurger.php +++ b/src/Utility/LSCachePurger.php @@ -2,10 +2,10 @@ namespace ACPL\FlarumLSCache\Utility; -use ACPL\FlarumLSCache\Command\LSCacheClearCommand; use ACPL\FlarumLSCache\Event\LSCachePurging; +use ACPL\FlarumLSCache\Job\PurgeCacheViaCliJob; +use Illuminate\Contracts\Queue\Queue; use Illuminate\Events\Dispatcher; -use Symfony\Component\Console\{Input\ArrayInput, Output\NullOutput}; use const PHP_SAPI; @@ -31,7 +31,7 @@ class LSCachePurger */ public static array $resourcesSupportedByEvent = ['discussion', 'post', 'user']; - public function __construct(protected readonly LSCacheClearCommand $cacheClearCommand, protected Dispatcher $events) + public function __construct(protected Dispatcher $events, protected Queue $queue) { } @@ -76,32 +76,15 @@ public function clearPurgeData(): void public function executePurge(): void { - if (empty(self::$purgeData) || (empty(self::$purgeData['paths']) || empty(self::$purgeData['tags']))) { + if (empty(self::$purgeData) || (empty(self::$purgeData['paths']) && empty(self::$purgeData['tags']))) { return; } if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { - $this->purgeViaCli(); - } - // else Data will be handled by middleware - } - - private function purgeViaCli(): void - { - $input = []; - - $this->events->dispatch(new LSCachePurging(self::$purgeData)); - - if (! empty(self::$purgeData['paths'])) { - $input['--path'] = self::$purgeData['paths']; - } - - if (! empty(self::$purgeData['tags'])) { - $input['--tag'] = self::$purgeData['tags']; - } - - $this->cacheClearCommand->run(new ArrayInput($input), new NullOutput()); - $this->clearPurgeData(); + $this->events->dispatch(new LSCachePurging(self::$purgeData)); + $this->clearPurgeData(); + $this->queue->push(new PurgeCacheViaCliJob(self::$purgeData)); + } // else purge will be handled by middleware } public static function isResourceSupportedByEvent(string $resource): bool From 337c001452a2050e71c13e40ad5382483b6cc108 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 13 Sep 2024 22:39:50 +0000 Subject: [PATCH 34/38] Apply fixes from StyleCI --- src/Job/PurgeCacheViaCliJob.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Job/PurgeCacheViaCliJob.php b/src/Job/PurgeCacheViaCliJob.php index dbba02a..759f56c 100644 --- a/src/Job/PurgeCacheViaCliJob.php +++ b/src/Job/PurgeCacheViaCliJob.php @@ -15,7 +15,9 @@ class PurgeCacheViaCliJob extends AbstractJob implements ShouldQueue * tags: string[] * } $data */ - public function __construct(protected array $data = ['paths' => [], 'tags' => []]) { } + public function __construct(protected array $data = ['paths' => [], 'tags' => []]) + { + } public function handle(LSCachePurgeCommand $command): void { From 1de0fc9628d45158b074c0358a865e127b384323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 14 Sep 2024 01:17:55 +0200 Subject: [PATCH 35/38] feat: generate less tags --- extend.php | 6 +++--- .../Flarum/Likes/FlarumLikesEventSubscriber.php | 2 +- .../Flarum/Tags/FlarumTagsEventSubscriber.php | 6 +++--- .../MovePosts/SychOMovePostsSubscriber.php | 1 - src/LSCache.php | 7 ++++++- src/Listener/DiscussionCachePurgeTrait.php | 2 +- src/Listener/PostEventSubscriber.php | 4 ++-- src/Listener/UserEventSubscriber.php | 17 +++++++++++------ src/Middleware/AbstractCacheTagsMiddleware.php | 4 +--- ...gsMiddleware.php => CacheTagsMiddleware.php} | 10 +++++++--- 10 files changed, 35 insertions(+), 24 deletions(-) rename src/Middleware/{LSTagsMiddleware.php => CacheTagsMiddleware.php} (79%) diff --git a/extend.php b/extend.php index f10ff07..b4ddcf1 100644 --- a/extend.php +++ b/extend.php @@ -29,7 +29,7 @@ }; use ACPL\FlarumLSCache\Middleware\{ CacheControlMiddleware, - LSTagsMiddleware, + CacheTagsMiddleware, LoginMiddleware, LogoutMiddleware, PurgeCacheMiddleware, @@ -63,8 +63,8 @@ (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, LogoutMiddleware::class), // Tag routes - (new Extend\Middleware('forum'))->add(LSTagsMiddleware::class), - (new Extend\Middleware('api'))->add(LSTagsMiddleware::class), + (new Extend\Middleware('forum'))->add(CacheTagsMiddleware::class), + (new Extend\Middleware('api'))->add(CacheTagsMiddleware::class), // Cache routes (new Extend\Middleware('forum'))->insertAfter(VaryCookieMiddleware::class, CacheControlMiddleware::class), diff --git a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php index 6ebb682..ba41cea 100644 --- a/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php +++ b/src/Compatibility/Flarum/Likes/FlarumLikesEventSubscriber.php @@ -18,7 +18,7 @@ public function subscribe(Dispatcher $events): void protected function handle(PostWasLiked|PostWasUnliked $event): void { $this->purger->addPurgeTags([ - 'posts.index', + 'posts', "post_{$event->post->id}", "discussion_{$event->post->discussion->id}", "user_{$event->post->user->id}", diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php index 9bee7cf..71109de 100644 --- a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php +++ b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php @@ -44,7 +44,7 @@ public function handleDiscussionWasTagged(DiscussionWasTagged $event): void "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", "user_{$event->discussion->user->username}", - 'tags.index', + 'tags', ...$this->generateCacheTagsForDiscussionTags($event->discussion), ]); } @@ -61,7 +61,7 @@ public function handleDiscussionEvents( } $this->purger->addPurgeTags([ - 'tags.index', + 'tags', ...$this->generateCacheTagsForDiscussionTags($event->discussion), ]); } @@ -77,7 +77,7 @@ public function handlePostEvents(PostDeleted|PostHidden|Posted|PostRestored $eve } $this->purger->addPurgeTags([ - 'tags.index', + 'tags', ...$this->generateCacheTagsForDiscussionTags($event->post->discussion), ]); } diff --git a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php index 3f3117f..c800dee 100644 --- a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php +++ b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php @@ -29,7 +29,6 @@ protected function handlePostsMoved(PostsMoved $event): void $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'posts.index', "discussion_{$event->sourceDiscussion->id}", "discussion_{$event->targetDiscussion->id}", ...$cacheTags, diff --git a/src/LSCache.php b/src/LSCache.php index 7239125..f6a7bdc 100644 --- a/src/LSCache.php +++ b/src/LSCache.php @@ -11,6 +11,11 @@ class LSCache public static function extractRootRouteName(string $name): string { - return Str::singular(explode('.', $name, 2)[0]); + return explode('.', $name, 2)[0]; + } + + public static function extractRootRouteSingularName(string $name): string + { + return Str::singular(self::extractRootRouteName($name)); } } diff --git a/src/Listener/DiscussionCachePurgeTrait.php b/src/Listener/DiscussionCachePurgeTrait.php index e8d09ef..f48e9c3 100644 --- a/src/Listener/DiscussionCachePurgeTrait.php +++ b/src/Listener/DiscussionCachePurgeTrait.php @@ -16,7 +16,7 @@ protected function handleDiscussionUpdatePurge(): void $this->purger->addPurgeTags([ 'default', 'index', - 'discussions.index', + 'discussions', ]); $purgeList = $this->settings->get('acpl-lscache.purge_on_discussion_update'); diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index e79d46e..44c4478 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -28,7 +28,7 @@ protected function handle(Hidden|Posted|Restored|PostWasApproved $event): void $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ - 'posts.index', + 'posts', "discussion_{$event->post->discussion_id}", "user_{$event->post->user_id}", "user_{$event->post->user_id}", @@ -43,7 +43,7 @@ protected function handleRevised(Revised $event): void // No need to purge homepage cache when post is revised $this->purger->addPurgeTags([ - 'posts.index', + 'posts', "discussion_{$event->post->discussion_id}", "user_{$event->post->user_id}", "user_{$event->post->user_id}", diff --git a/src/Listener/UserEventSubscriber.php b/src/Listener/UserEventSubscriber.php index 2f800ed..ceee8a9 100644 --- a/src/Listener/UserEventSubscriber.php +++ b/src/Listener/UserEventSubscriber.php @@ -18,16 +18,21 @@ public function subscribe(Dispatcher $events): void /** Purge discussions where user has posted. */ public function handleUserWithPosts(AvatarChanged|GroupsChanged|Renamed $event): void { - // TODO: If user has a lot discussion chunk it and push to the queue job - /** @phpstan-ignore-next-line Call to an undefined method Illuminate\Database\Eloquent\Relations\Relation::pluck(). */ - $discussions = $event->user->posts()->getRelation('discussion')->pluck('id')->toArray(); - $this->purger->addPurgeTags([ "user_{$event->user->id}", "user_{$event->user->username}", - 'posts.index', - 'discussions.index', + 'posts', + 'discussions', ...array_map(fn ($id) => "discussion_$id", $discussions), ]); + + $discussionCount = $event->user->posts()->getRelation('discussion')->distinct()->count(); + if ($discussionCount < 50) { + /** @phpstan-ignore-next-line Call to an undefined method Illuminate\Database\Eloquent\Relations\Relation::pluck(). */ + $discussions = $event->user->posts()->getRelation('discussion')->pluck('id')->toArray(); + $this->purger->addPurgeTags([ + + ]); + } } } diff --git a/src/Middleware/AbstractCacheTagsMiddleware.php b/src/Middleware/AbstractCacheTagsMiddleware.php index be1d617..5f02389 100644 --- a/src/Middleware/AbstractCacheTagsMiddleware.php +++ b/src/Middleware/AbstractCacheTagsMiddleware.php @@ -38,8 +38,6 @@ protected function addLSCacheTagsToResponse(ResponseInterface $response, array $ ); } - $newTags = array_unique($newTags); - - return $response->withHeader(LSCacheHeader::TAG, implode(',', $newTags)); + return $response->withHeader(LSCacheHeader::TAG, implode(',', array_unique($newTags))); } } diff --git a/src/Middleware/LSTagsMiddleware.php b/src/Middleware/CacheTagsMiddleware.php similarity index 79% rename from src/Middleware/LSTagsMiddleware.php rename to src/Middleware/CacheTagsMiddleware.php index 45b8664..920ee7b 100644 --- a/src/Middleware/LSTagsMiddleware.php +++ b/src/Middleware/CacheTagsMiddleware.php @@ -6,7 +6,7 @@ use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; use Psr\Http\Server\RequestHandlerInterface; -class LSTagsMiddleware extends AbstractCacheTagsMiddleware +class CacheTagsMiddleware extends AbstractCacheTagsMiddleware { protected function processTags( ServerRequestInterface $request, @@ -16,10 +16,14 @@ protected function processTags( $routeName = $this->currentRouteName; $params = $request->getAttribute('routeParameters'); - $tagParams = [$routeName]; + if (str_ends_with($routeName, '.index')) { + $tagParams = [LSCache::extractRootRouteName($routeName)]; + } else { + $tagParams = [$routeName]; + } if (! empty($params)) { - $rootRouteName = LSCache::extractRootRouteName($routeName); + $rootRouteName = LSCache::extractRootRouteSingularName($routeName); // Discussion if (! empty($params['id'])) { From 6445a9e5bafd40a6f6ecdbe7a8a5a44fdc95459b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 14 Sep 2024 01:30:58 +0200 Subject: [PATCH 36/38] refactor: simplify code --- ...kWinkelmannAuthorChangeEventSubscriber.php | 2 +- .../Flarum/Tags/FlarumTagsEventSubscriber.php | 2 +- .../MovePosts/SychOMovePostsSubscriber.php | 2 +- src/Listener/DiscussionCachePurgeTrait.php | 2 +- src/Listener/DiscussionEventSubscriber.php | 2 +- src/Listener/PostEventSubscriber.php | 25 +++++-------------- src/Middleware/PurgeCacheMiddleware.php | 2 +- 7 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php index 17c5d14..a136640 100644 --- a/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php +++ b/src/Compatibility/ClarkWinkelmann/AuthorChange/ClarkWinkelmannAuthorChangeEventSubscriber.php @@ -27,7 +27,7 @@ public function subscribe(Dispatcher $events): void protected function handleDiscussion(DiscussionCreateDateChanged|DiscussionUserChanged $event): void { - $this->handleDiscussionUpdatePurge(); + $this->handleDiscussionRelatedPurge(); $this->purger->addPurgeTags([ "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", diff --git a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php index 71109de..ac8a572 100644 --- a/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php +++ b/src/Compatibility/Flarum/Tags/FlarumTagsEventSubscriber.php @@ -39,7 +39,7 @@ public function subscribe(Dispatcher $events): void public function handleDiscussionWasTagged(DiscussionWasTagged $event): void { - $this->handleDiscussionUpdatePurge(); + $this->handleDiscussionRelatedPurge(); $this->purger->addPurgeTags([ "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", diff --git a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php index c800dee..84db67f 100644 --- a/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php +++ b/src/Compatibility/SychO/MovePosts/SychOMovePostsSubscriber.php @@ -27,7 +27,7 @@ protected function handlePostsMoved(PostsMoved $event): void $cacheTags[] = "user_{$post->user->username}"; }); - $this->handleDiscussionUpdatePurge(); + $this->handleDiscussionRelatedPurge(); $this->purger->addPurgeTags([ "discussion_{$event->sourceDiscussion->id}", "discussion_{$event->targetDiscussion->id}", diff --git a/src/Listener/DiscussionCachePurgeTrait.php b/src/Listener/DiscussionCachePurgeTrait.php index f48e9c3..d5c0cdc 100644 --- a/src/Listener/DiscussionCachePurgeTrait.php +++ b/src/Listener/DiscussionCachePurgeTrait.php @@ -11,7 +11,7 @@ trait DiscussionCachePurgeTrait protected SettingsRepositoryInterface $settings; protected LSCachePurger $purger; - protected function handleDiscussionUpdatePurge(): void + protected function handleDiscussionRelatedPurge(): void { $this->purger->addPurgeTags([ 'default', diff --git a/src/Listener/DiscussionEventSubscriber.php b/src/Listener/DiscussionEventSubscriber.php index f73b1dd..0a6948c 100644 --- a/src/Listener/DiscussionEventSubscriber.php +++ b/src/Listener/DiscussionEventSubscriber.php @@ -25,7 +25,7 @@ protected function handle(Deleted|Hidden|Started|Restored|Renamed $event): void return; } - $this->handleDiscussionUpdatePurge(); + $this->handleDiscussionRelatedPurge(); $this->purger->addPurgeTags([ "discussion_{$event->discussion->id}", "user_{$event->discussion->user->id}", diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index 44c4478..0616927 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -12,42 +12,29 @@ class PostEventSubscriber extends AbstractCachePurgeSubscriber public function subscribe(Dispatcher $events): void { - $shared = [Hidden::class, Posted::class, Restored::class, PostWasApproved::class]; - foreach ($shared as $event) { + $postEvents = [Hidden::class, Posted::class, Restored::class, PostWasApproved::class, Revised::class]; + foreach ($postEvents as $event) { $this->addPurgeListener($events, $event, [$this, 'handle']); } - - $this->addPurgeListener($events, Revised::class, [$this, 'handleRevised']); } - protected function handle(Hidden|Posted|Restored|PostWasApproved $event): void + + protected function handle(Hidden|Posted|Restored|PostWasApproved|Revised $event): void { if (! $this->shouldPurge($event)) { return; } - $this->handleDiscussionUpdatePurge(); $this->purger->addPurgeTags([ 'posts', "discussion_{$event->post->discussion_id}", "user_{$event->post->user_id}", "user_{$event->post->user_id}", ]); - } - protected function handleRevised(Revised $event): void - { - if (! $this->shouldPurge($event)) { - return; + if (! $event instanceof Revised) { + $this->handleDiscussionRelatedPurge(); } - - // No need to purge homepage cache when post is revised - $this->purger->addPurgeTags([ - 'posts', - "discussion_{$event->post->discussion_id}", - "user_{$event->post->user_id}", - "user_{$event->post->user_id}", - ]); } protected function shouldPurge(Deleted|Hidden|Posted|Restored|Revised|PostWasApproved $event): bool diff --git a/src/Middleware/PurgeCacheMiddleware.php b/src/Middleware/PurgeCacheMiddleware.php index 073a971..853eb31 100644 --- a/src/Middleware/PurgeCacheMiddleware.php +++ b/src/Middleware/PurgeCacheMiddleware.php @@ -11,7 +11,7 @@ class PurgeCacheMiddleware extends AbstractPurgeCacheMiddleware protected function preparePurgeData(ServerRequestInterface $request): void { $routeName = $this->currentRouteName; - $rootRouteName = LSCache::extractRootRouteName($routeName); + $rootRouteName = LSCache::extractRootRouteSingularName($routeName); $params = $this->getRouteParams($request); if (! empty($params['id']) && $this->shouldPurgeRoute($rootRouteName, $routeName)) { From 7c4723078edc06151b095f799c31a0dbe5189130 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 13 Sep 2024 23:31:10 +0000 Subject: [PATCH 37/38] Apply fixes from StyleCI --- src/Listener/PostEventSubscriber.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Listener/PostEventSubscriber.php b/src/Listener/PostEventSubscriber.php index 0616927..230b15f 100644 --- a/src/Listener/PostEventSubscriber.php +++ b/src/Listener/PostEventSubscriber.php @@ -18,7 +18,6 @@ public function subscribe(Dispatcher $events): void } } - protected function handle(Hidden|Posted|Restored|PostWasApproved|Revised $event): void { if (! $this->shouldPurge($event)) { From e095732fa2c2065344a772d71098946f2bc2f8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ca=C5=82ka?= <25438601+rafaucau@users.noreply.github.com> Date: Sat, 14 Sep 2024 02:15:59 +0200 Subject: [PATCH 38/38] fix: use user Deleting event instead of Deleted to access user posts --- src/Listener/UserEventSubscriber.php | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Listener/UserEventSubscriber.php b/src/Listener/UserEventSubscriber.php index ceee8a9..0ad9c09 100644 --- a/src/Listener/UserEventSubscriber.php +++ b/src/Listener/UserEventSubscriber.php @@ -2,37 +2,32 @@ namespace ACPL\FlarumLSCache\Listener; -use Flarum\User\Event\{AvatarChanged, Deleted, GroupsChanged, Renamed}; +use Flarum\User\Event\{AvatarChanged, Deleting, GroupsChanged, Renamed}; use Illuminate\Contracts\Events\Dispatcher; class UserEventSubscriber extends AbstractCachePurgeSubscriber { public function subscribe(Dispatcher $events): void { - $shared = [AvatarChanged::class, Deleted::class, GroupsChanged::class, Renamed::class]; + $shared = [AvatarChanged::class, Deleting::class, GroupsChanged::class, Renamed::class]; foreach ($shared as $event) { $this->addPurgeListener($events, $event, [$this, 'handleUserWithPosts']); } } /** Purge discussions where user has posted. */ - public function handleUserWithPosts(AvatarChanged|GroupsChanged|Renamed $event): void + public function handleUserWithPosts(AvatarChanged|Deleting|GroupsChanged|Renamed $event): void { $this->purger->addPurgeTags([ "user_{$event->user->id}", "user_{$event->user->username}", 'posts', 'discussions', - ...array_map(fn ($id) => "discussion_$id", $discussions), + // TODO: If user has a lot of discussions chunk it and push to the queue job + ...array_map( + fn ($id) => "discussion_$id", + $event->user->posts()->pluck('discussion_id')->toArray(), + ), ]); - - $discussionCount = $event->user->posts()->getRelation('discussion')->distinct()->count(); - if ($discussionCount < 50) { - /** @phpstan-ignore-next-line Call to an undefined method Illuminate\Database\Eloquent\Relations\Relation::pluck(). */ - $discussions = $event->user->posts()->getRelation('discussion')->pluck('id')->toArray(); - $this->purger->addPurgeTags([ - - ]); - } } }