<?php
/*
* Author: Dominik Piekarski <code@dompie.de>
* Created at: 2022/08/18 15:14
*/
declare(strict_types=1);
namespace App\EventSubscriber;
use App\Event\Content\BlogEntryChangedEvent;
use App\Event\Content\ContentCommentCreatedEvent;
use App\Event\Content\GuestbookEntryApprovedEvent;
use App\Event\Content\GuestbookEntryCommentedEvent;
use App\Event\Content\GuestbookEntryCreatedEvent;
use App\Event\Content\GuestbookEntryRemovedEvent;
use App\Event\EventUsernameInterface;
use App\Event\Livecam\LivecamEndedEvent;
use App\Event\Livecam\LivecamEventInterface;
use App\Event\Livecam\LivecamJoinedEvent;
use App\Event\Livecam\LivecamStartedEvent;
use App\Event\Livecam\LivecamUnjoinedEvent;
use App\Event\User\MemberProfileUpdatedEvent;
use App\Infrastructure\PageCacheHelper;
use App\Security\ApiUser;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\Event\LogoutEvent;
use Symfony\Contracts\EventDispatcher\Event;
class PageCacheSubscriber implements EventSubscriberInterface
{
private PageCacheHelper $pageCache;
private RequestStack $requestStack;
private RouterInterface $router;
public function __construct(PageCacheHelper $pageCache, RequestStack $stack, RouterInterface $router)
{
$this->pageCache = $pageCache;
$this->requestStack = $stack;
$this->router = $router;
}
public static function getSubscribedEvents()
{
return [
LivecamStartedEvent::class => ['onLivecamEventEnqueuePageCacheUpdate'],
LivecamJoinedEvent::class => ['onLivecamEventEnqueuePageCacheUpdate'],
LivecamUnjoinedEvent::class => ['onLivecamEventEnqueuePageCacheUpdate'],
LivecamEndedEvent::class => ['onLivecamEventEnqueuePageCacheUpdate'],
InteractiveLoginEvent::class => ['logInOutPageCacheUpdate', -1],
LogoutEvent::class => ['logInOutPageCacheUpdate', 1],
ContentCommentCreatedEvent::class => ['onContentCommentCreatedUpdatePageCache', 1],
MemberProfileUpdatedEvent::class => ['onMemberProfileEditUpdatePageCache', 1],
GuestbookEntryCreatedEvent::class => ['onGuestbookEntryChangeUpdatePageCache', 1],
GuestbookEntryCommentedEvent::class => ['onGuestbookEntryChangeUpdatePageCache', 1],
GuestbookEntryApprovedEvent::class => ['onGuestbookEntryChangeUpdatePageCache', 1],
GuestbookEntryRemovedEvent::class => ['onGuestbookEntryChangeUpdatePageCache', 1],
BlogEntryChangedEvent::class => ['onBlogEntryChangeUpdatePageCache', 1],
];
}
public function onLivecamEventEnqueuePageCacheUpdate(LivecamEventInterface $event): void
{
$request = $this->requestStack->getMainRequest();
if (null === $request) {
return;
}
$httpHost = $request->getHttpHost();
$paths[] = $this->router->generate('app_livecam_index');
for ($i = 2; $i < 10; $i++) {
$paths[] = $this->router->generate('app_livecam_index', ['page' => $i]);
}
$profileUrl = $this->router->generate('app_user_profile_detail', ['username' => $event->getStreamOwnerUsername()]);
$this->pageCache->enqueueMemberProfileUrls($httpHost, [$profileUrl], true);
$this->pageCache->enqueuePublicProfileUrls($httpHost, [$profileUrl], true);
$this->pageCache->enqueueMemberContentUrls($httpHost, $paths, true);
$this->pageCache->enqueuePublicContentUrls($httpHost, $paths, true);
}
public function logInOutPageCacheUpdate(Event $event): void
{
if ($event instanceof InteractiveLoginEvent) {
if (null === $user = $event->getAuthenticationToken()->getUser()) {
return;
}
if (!$user instanceof ApiUser) {
return;
}
$username = $user->getUsername();
$httpHost = $event->getRequest()->getHttpHost();
}
if ($event instanceof LogoutEvent) {
$token = $event->getToken();
if (null === $token || null === $user = $token->getUser()) {
return;
}
if (!$user instanceof ApiUser) {
return;
}
$username = $user->getUsername();
$httpHost = $event->getRequest()->getHttpHost();
}
$urls = $this->generateProfileUrls($username, $user);
$this->pageCache->enqueueMemberProfileUrls($httpHost, $urls, true);
$this->pageCache->enqueuePublicProfileUrls($httpHost, $urls, true);
}
public function onContentCommentCreatedUpdatePageCache(ContentCommentCreatedEvent $event): void
{
$request = $this->requestStack->getMainRequest();
if (null === $request) {
return;
}
$httpHost = $request->getHttpHost();
$urls = [];
if ($event->isImageset()) {
$urls[] = $this->router->generate('app_content_imageset_detail', ['slug' => $event->getSlug()]);
}
if ($event->isVideo()) {
$urls[] = $this->router->generate('app_content_video_detail', ['slug' => $event->getSlug()]);
}
$this->pageCache->enqueueMemberContentUrls($httpHost, $urls, true);
$this->pageCache->enqueuePublicContentUrls($httpHost, $urls, true);
}
public function onMemberProfileEditUpdatePageCache(EventUsernameInterface $event): void
{
$request = $this->requestStack->getMainRequest();
if (null === $request) {
return;
}
$httpHost = $request->getHttpHost();
$urls[] = $this->generateProfileUrls($event->getUsername());
$this->pageCache->enqueueMemberProfileUrls($httpHost, $urls, true);
$this->pageCache->enqueuePublicProfileUrls($httpHost, $urls, true);
}
public function onGuestbookEntryChangeUpdatePageCache(EventUsernameInterface $event): void
{
$request = $this->requestStack->getMainRequest();
if (null === $request) {
return;
}
$httpHost = $request->getHttpHost();
$urls[] = $this->router->generate('app_user_profile_guestbook', ['username' => $event->getUsername()]);
$this->pageCache->enqueueMemberProfileUrls($httpHost, $urls, true);
$this->pageCache->enqueuePublicProfileUrls($httpHost, $urls, true);
}
public function onBlogEntryChangeUpdatePageCache(BlogEntryChangedEvent $event): void
{
$request = $this->requestStack->getMainRequest();
if (null === $request) {
return;
}
$httpHost = $request->getHttpHost();
$route = 'app_user_profile_blog';
$urls[] = $this->router->generate($route, ['username' => $event->getUsername()]);
$this->pageCache->enqueueMemberProfileUrls($httpHost, $urls, true);
$this->pageCache->enqueuePublicProfileUrls($httpHost, $urls, true);
}
private function generateProfileUrls(string $username, ?ApiUser $user = null): array
{
//Only append these routes if user is amateur...
if ($user instanceof ApiUser && $user->hasRole('ROLE_AMATEUR')) {
$urls[] = $this->router->generate('app_user_profile_videos', ['username' => $username]);
$urls[] = $this->router->generate('app_user_profile_imagesets', ['username' => $username]);
$urls[] = $this->router->generate('app_user_profile_blog', ['username' => $username]);
}
//...or we do not know if it is a member or an amateur.
if ($user === null) {
$urls[] = $this->router->generate('app_user_profile_videos', ['username' => $username]);
$urls[] = $this->router->generate('app_user_profile_imagesets', ['username' => $username]);
$urls[] = $this->router->generate('app_user_profile_blog', ['username' => $username]);
}
$urls[] = $this->router->generate('app_user_profile_detail', ['username' => $username]);
$urls[] = $this->router->generate('app_user_profile_about', ['username' => $username]);
$urls[] = $this->router->generate('app_user_profile_guestbook', ['username' => $username]);
return $urls;
}
}