diff --git a/src/Twig/Components/ActiveUsersComponent.php b/src/Twig/Components/ActiveUsersComponent.php index 8d45f4d42..6841f8893 100644 --- a/src/Twig/Components/ActiveUsersComponent.php +++ b/src/Twig/Components/ActiveUsersComponent.php @@ -5,41 +5,36 @@ namespace App\Twig\Components; use App\Entity\Magazine; +use App\Entity\User; use App\Repository\UserRepository; -use Symfony\Component\HttpFoundation\RequestStack; +use App\Service\SettingsManager; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; -use Symfony\UX\TwigComponent\ComponentAttributes; -use Twig\Environment; -#[AsTwigComponent('active_users', template: 'components/_cached.html.twig')] +#[AsTwigComponent('active_users')] final class ActiveUsersComponent { - public ?Magazine $magazine = null; + /** @var User[] */ + public array $users = []; public function __construct( private readonly UserRepository $userRepository, private readonly CacheInterface $cache, - private readonly Environment $twig, - private readonly RequestStack $requestStack + private readonly SettingsManager $settingsManager, ) { } - public function getHtml(ComponentAttributes $attributes): string + public function mount(?Magazine $magazine): void { - return $this->cache->get( - "active_users_{$this->magazine?->getId()}_{$this->requestStack->getCurrentRequest()?->getLocale()}", - function (ItemInterface $item) { - $item->expiresAfter(60); - - return $this->twig->render( - 'components/active_users.html.twig', - [ - 'users' => $this->userRepository->findActiveUsers($this->magazine), - ] - ); + $activeUserIds = $this->cache->get("active_users_{$magazine?->getId()}_{$this->settingsManager->getLocale()}", + function (ItemInterface $item) use ($magazine) { + $item->expiresAfter(60 * 5); // 5 minutes + + return array_map(fn (User $user) => $user->getId(), $this->userRepository->findActiveUsers($magazine)); } ); + + $this->users = $this->userRepository->findBy(['id' => $activeUserIds]); } } diff --git a/src/Twig/Components/RelatedEntriesComponent.php b/src/Twig/Components/RelatedEntriesComponent.php index 3c7c3f391..febe94156 100644 --- a/src/Twig/Components/RelatedEntriesComponent.php +++ b/src/Twig/Components/RelatedEntriesComponent.php @@ -7,15 +7,12 @@ use App\Entity\Entry; use App\Repository\EntryRepository; use App\Service\MentionManager; -use Symfony\Component\HttpFoundation\RequestStack; +use App\Service\SettingsManager; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; -use Symfony\UX\TwigComponent\Attribute\PostMount; -use Symfony\UX\TwigComponent\ComponentAttributes; -use Twig\Environment; -#[AsTwigComponent('related_entries', template: 'components/_cached.html.twig')] +#[AsTwigComponent('related_entries')] final class RelatedEntriesComponent { public const TYPE_TAG = 'tag'; @@ -23,51 +20,45 @@ final class RelatedEntriesComponent public const TYPE_RANDOM = 'random'; public int $limit = 4; - public ?string $tag = null; - public ?string $magazine = null; public ?string $type = self::TYPE_RANDOM; public ?Entry $entry = null; public string $title = 'random_entries'; + /** @var Entry[] */ + public array $entries = []; + public function __construct( private readonly EntryRepository $repository, private readonly CacheInterface $cache, - private readonly Environment $twig, - private readonly RequestStack $requestStack, + private readonly SettingsManager $settingsManager, private readonly MentionManager $mentionManager ) { } - #[PostMount] - public function postMount(array $attr): array + public function mount(?string $magazine, ?string $tag): void { - if ($this->tag) { + if ($tag) { $this->title = 'related_entries'; $this->type = self::TYPE_TAG; } - if ($this->magazine) { + if ($magazine) { $this->title = 'related_entries'; $this->type = self::TYPE_MAGAZINE; } - return $attr; - } - - public function getHtml(ComponentAttributes $attributes): string - { $entryId = $this->entry?->getId(); - $magazine = str_replace('@', '', $this->magazine ?? ''); + $magazine = str_replace('@', '', $magazine ?? ''); - return $this->cache->get( - "related_entries_{$magazine}_{$this->tag}_{$entryId}_{$this->type}_{$this->requestStack->getCurrentRequest()?->getLocale()}", - function (ItemInterface $item) use ($attributes) { - $item->expiresAfter(60); + $entryIds = $this->cache->get( + "related_entries_{$magazine}_{$tag}_{$entryId}_{$this->type}_{$this->settingsManager->getLocale()}", + function (ItemInterface $item) use ($magazine, $tag) { + $item->expiresAfter(60 * 5); // 5 minutes $entries = match ($this->type) { - self::TYPE_TAG => $this->repository->findRelatedByMagazine($this->tag, $this->limit + 20), + self::TYPE_TAG => $this->repository->findRelatedByMagazine($tag, $this->limit + 20), self::TYPE_MAGAZINE => $this->repository->findRelatedByTag( - $this->mentionManager->getUsername($this->magazine), + $this->mentionManager->getUsername($magazine), $this->limit + 20 ), default => $this->repository->findLast($this->limit + 150), @@ -80,15 +71,10 @@ function (ItemInterface $item) use ($attributes) { $entries = \array_slice($entries, 0, $this->limit); } - return $this->twig->render( - 'components/related_entries.html.twig', - [ - 'attributes' => $attributes, - 'entries' => $entries, - 'title' => $this->title, - ] - ); + return array_map(fn (Entry $entry) => $entry->getId(), $entries); } ); + + $this->entries = $this->repository->findBy(['id' => $entryIds]); } } diff --git a/src/Twig/Components/RelatedMagazinesComponent.php b/src/Twig/Components/RelatedMagazinesComponent.php index 86de89b12..741dea67f 100644 --- a/src/Twig/Components/RelatedMagazinesComponent.php +++ b/src/Twig/Components/RelatedMagazinesComponent.php @@ -4,16 +4,14 @@ namespace App\Twig\Components; +use App\Entity\Magazine; use App\Repository\MagazineRepository; -use Symfony\Component\HttpFoundation\RequestStack; +use App\Service\SettingsManager; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; -use Symfony\UX\TwigComponent\Attribute\PostMount; -use Symfony\UX\TwigComponent\ComponentAttributes; -use Twig\Environment; -#[AsTwigComponent('related_magazines', template: 'components/_cached.html.twig')] +#[AsTwigComponent('related_magazines')] final class RelatedMagazinesComponent { public const TYPE_TAG = 'tag'; @@ -21,61 +19,49 @@ final class RelatedMagazinesComponent public const TYPE_RANDOM = 'random'; public int $limit = 4; - public ?string $tag = null; - public ?string $magazine = null; public ?string $type = self::TYPE_RANDOM; public string $title = 'random_magazines'; + /** @var Magazine[] */ + public array $magazines = []; public function __construct( private readonly MagazineRepository $repository, private readonly CacheInterface $cache, - private readonly Environment $twig, - private readonly RequestStack $requestStack + private readonly SettingsManager $settingsManager, ) { } - #[PostMount] - public function postMount(array $attr): array + public function mount(?string $magazine, ?string $tag): void { - if ($this->tag) { + if ($tag) { $this->title = 'related_magazines'; $this->type = self::TYPE_TAG; } - if ($this->magazine) { + if ($magazine) { $this->title = 'related_magazines'; $this->type = self::TYPE_MAGAZINE; } - return $attr; - } - - public function getHtml(ComponentAttributes $attributes): string - { - $magazine = str_replace('@', '', $this->magazine ?? ''); + $magazine = str_replace('@', '', $magazine ?? ''); - return $this->cache->get( - "related_magazines_{$magazine}_{$this->tag}_{$this->type}_{$this->requestStack->getCurrentRequest()?->getLocale()}", - function (ItemInterface $item) use ($attributes, $magazine) { - $item->expiresAfter(60); + $magazineIds = $this->cache->get( + "related_magazines_{$magazine}_{$tag}_{$this->type}_{$this->settingsManager->getLocale()}", + function (ItemInterface $item) use ($magazine, $tag) { + $item->expiresAfter(60 * 5); // 5 minutes $magazines = match ($this->type) { - self::TYPE_TAG => $this->repository->findRelated($this->tag), + self::TYPE_TAG => $this->repository->findRelated($tag), self::TYPE_MAGAZINE => $this->repository->findRelated($magazine), default => $this->repository->findRandom(), }; - $magazines = array_filter($magazines, fn ($m) => $m->name !== $this->magazine); + $magazines = array_filter($magazines, fn ($m) => $m->name !== $magazine); - return $this->twig->render( - 'components/related_magazines.html.twig', - [ - 'attributes' => $attributes, - 'magazines' => $magazines, - 'title' => $this->title, - ] - ); + return array_map(fn (Magazine $magazine) => $magazine->getId(), $magazines); } ); + + $this->magazines = $this->repository->findBy(['id' => $magazineIds]); } } diff --git a/src/Twig/Components/RelatedPostsComponent.php b/src/Twig/Components/RelatedPostsComponent.php index 112aeadc1..bfc1d944d 100644 --- a/src/Twig/Components/RelatedPostsComponent.php +++ b/src/Twig/Components/RelatedPostsComponent.php @@ -7,15 +7,12 @@ use App\Entity\Post; use App\Repository\PostRepository; use App\Service\MentionManager; -use Symfony\Component\HttpFoundation\RequestStack; +use App\Service\SettingsManager; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; -use Symfony\UX\TwigComponent\Attribute\PostMount; -use Symfony\UX\TwigComponent\ComponentAttributes; -use Twig\Environment; -#[AsTwigComponent('related_posts', template: 'components/_cached.html.twig')] +#[AsTwigComponent('related_posts')] final class RelatedPostsComponent { public const TYPE_TAG = 'tag'; @@ -23,51 +20,44 @@ final class RelatedPostsComponent public const TYPE_RANDOM = 'random'; public int $limit = 4; - public ?string $tag = null; - public ?string $magazine = null; public ?string $type = self::TYPE_RANDOM; public ?Post $post = null; public string $title = 'random_posts'; + /** @var Post[] */ + public array $posts = []; public function __construct( private readonly PostRepository $repository, private readonly CacheInterface $cache, - private readonly Environment $twig, - private readonly RequestStack $requestStack, + private readonly SettingsManager $settingsManager, private readonly MentionManager $mentionManager ) { } - #[PostMount] - public function postMount(array $attr): array + public function mount(?string $magazine, ?string $tag): void { - if ($this->tag) { + if ($tag) { $this->title = 'related_posts'; $this->type = self::TYPE_TAG; } - if ($this->magazine) { + if ($magazine) { $this->title = 'related_posts'; $this->type = self::TYPE_MAGAZINE; } - return $attr; - } - - public function getHtml(ComponentAttributes $attributes): string - { $postId = $this->post?->getId(); - $magazine = str_replace('@', '', $this->magazine ?? ''); + $magazine = str_replace('@', '', $magazine ?? ''); - return $this->cache->get( - "related_posts_{$magazine}_{$this->tag}_{$postId}_{$this->type}_{$this->requestStack->getCurrentRequest()?->getLocale()}", - function (ItemInterface $item) use ($attributes) { - $item->expiresAfter(60); + $postIds = $this->cache->get( + "related_posts_{$magazine}_{$tag}_{$postId}_{$this->type}_{$this->settingsManager->getLocale()}", + function (ItemInterface $item) use ($magazine, $tag) { + $item->expiresAfter(60 * 5); // 5 minutes $posts = match ($this->type) { - self::TYPE_TAG => $this->repository->findRelatedByMagazine($this->tag, $this->limit + 20), + self::TYPE_TAG => $this->repository->findRelatedByMagazine($tag, $this->limit + 20), self::TYPE_MAGAZINE => $this->repository->findRelatedByTag( - $this->mentionManager->getUsername($this->magazine), + $this->mentionManager->getUsername($magazine), $this->limit + 20 ), default => $this->repository->findLast($this->limit + 150), @@ -80,15 +70,10 @@ function (ItemInterface $item) use ($attributes) { $posts = \array_slice($posts, 0, $this->limit); } - return $this->twig->render( - 'components/related_posts.html.twig', - [ - 'attributes' => $attributes, - 'posts' => $posts, - 'title' => $this->title, - ] - ); + return array_map(fn (Post $post) => $post->getId(), $posts); } ); + + $this->posts = $this->repository->findBy(['id' => $postIds]); } }