You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.8 KiB
103 lines
3.8 KiB
<?php |
|
|
|
declare(strict_types=1); |
|
|
|
namespace App\Controller; |
|
|
|
use App\Service\MagazineContentService; |
|
use App\Service\MagazineRefresher; |
|
use Psr\Log\LoggerInterface; |
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; |
|
use Symfony\Component\HttpFoundation\JsonResponse; |
|
use Symfony\Component\HttpFoundation\Request; |
|
use Symfony\Component\HttpFoundation\Response; |
|
use Symfony\Component\HttpKernel\Attribute\AsController; |
|
use Symfony\Component\Routing\Attribute\Route; |
|
use Twig\Environment; |
|
|
|
/** Stale-first: the main request only reads {@see \App\Service\MagazineIndexStore}; this refetches Nostr, updates that store, and returns HTML fragments for Stimulus to patch the document. */ |
|
#[AsController] |
|
final class MagazineSyncController |
|
{ |
|
public function __construct( |
|
private readonly Environment $twig, |
|
private readonly MagazineRefresher $refresher, |
|
private readonly MagazineContentService $magazineContent, |
|
private readonly ParameterBagInterface $params, |
|
private readonly LoggerInterface $logger, |
|
) { |
|
} |
|
|
|
#[Route('/ux/magazine-sync', name: 'ux_magazine_sync', methods: ['GET'])] |
|
public function __invoke(Request $request): JsonResponse |
|
{ |
|
try { |
|
$page = (string) $request->query->get('page', 'article'); |
|
if (!\in_array($page, ['home', 'category', 'article', 'articles'], true)) { |
|
$page = 'article'; |
|
} |
|
$slug = (string) $request->query->get('slug', ''); |
|
|
|
$prefer = $slug !== '' ? [$slug] : []; |
|
|
|
try { |
|
$this->refresher->refreshFromRelays(20, $prefer); |
|
} catch (\Throwable $e) { |
|
$this->logger->warning('MagazineSyncController: refresh failed', [ |
|
'message' => $e->getMessage(), |
|
'exception' => $e, |
|
]); |
|
|
|
return new JsonResponse( |
|
['ok' => false, 'error' => 'refresh_failed', 'message' => $e->getMessage()], |
|
Response::HTTP_OK |
|
); |
|
} |
|
|
|
$community = (bool) $this->params->get('community_articles'); |
|
$tags = $this->magazineContent->getHomeCategoryAIndexTagsFromStoreOnly(); |
|
$globals = [ |
|
'magazine_community_articles' => $community, |
|
]; |
|
|
|
$header = $this->twig->render('ux/magazine/header_ul.html.twig', array_merge($globals, [ |
|
'cats' => $tags, |
|
])); |
|
|
|
$body = null; |
|
if ($page === 'home') { |
|
$body = $this->twig->render('ux/magazine/home_body.html.twig', array_merge($globals, [ |
|
'indices' => $tags, |
|
])); |
|
} elseif ($page === 'category' && $slug !== '') { |
|
$data = $this->magazineContent->getCategoryPageData($slug); |
|
$body = $this->twig->render('ux/magazine/category_body.html.twig', array_merge($globals, [ |
|
'list' => $data['list'], |
|
'category' => $data['category'], |
|
])); |
|
} elseif ($page === 'articles') { |
|
$body = null; |
|
} |
|
|
|
return new JsonResponse([ |
|
'ok' => true, |
|
'header' => $header, |
|
'body' => $body, |
|
]); |
|
} catch (\Throwable $e) { |
|
$this->logger->error('MagazineSyncController: unexpected failure', [ |
|
'message' => $e->getMessage(), |
|
'exception' => $e, |
|
]); |
|
|
|
return new JsonResponse( |
|
[ |
|
'ok' => false, |
|
'error' => 'server_error', |
|
'message' => 'Magazine UI sync could not be rendered.', |
|
], |
|
Response::HTTP_OK |
|
); |
|
} |
|
} |
|
}
|
|
|