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.
130 lines
4.8 KiB
130 lines
4.8 KiB
<?php |
|
|
|
declare(strict_types=1); |
|
|
|
namespace App\Controller\Administration; |
|
|
|
use App\Entity\Article; |
|
use Doctrine\ORM\EntityManagerInterface; |
|
use Redis as RedisClient; |
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
|
use Symfony\Component\HttpFoundation\Response; |
|
use Symfony\Component\Routing\Attribute\Route; |
|
use Symfony\Component\Security\Http\Attribute\IsGranted; |
|
use Symfony\Contracts\Cache\CacheInterface; |
|
|
|
class MagazineAdminController extends AbstractController |
|
{ |
|
#[Route('/admin/magazines', name: 'admin_magazines')] |
|
#[IsGranted('ROLE_ADMIN')] |
|
public function index(RedisClient $redis, CacheInterface $redisCache, EntityManagerInterface $em): Response |
|
{ |
|
// 1) Collect known top-level magazine slugs from Redis set (populated on publish) |
|
$slugs = []; |
|
try { |
|
$members = $redis->sMembers('magazine_slugs'); |
|
if (is_array($members)) { |
|
$slugs = array_values(array_unique(array_filter($members))); |
|
} |
|
} catch (\Throwable) { |
|
// ignore set errors |
|
} |
|
|
|
// 2) Ensure the known main magazine is included if present in cache |
|
try { |
|
$main = $redisCache->get('magazine-newsroom-magazine-by-newsroom', fn() => null); |
|
if ($main) { |
|
if (!in_array('newsroom-magazine-by-newsroom', $slugs, true)) { |
|
$slugs[] = 'newsroom-magazine-by-newsroom'; |
|
} |
|
} |
|
} catch (\Throwable) { |
|
// ignore |
|
} |
|
|
|
// 3) Load magazine events and build structure |
|
$magazines = []; |
|
|
|
// Helper to parse tags |
|
$parse = function($event): array { |
|
$title = null; $slug = null; $a = []; |
|
foreach ((array) $event->getTags() as $tag) { |
|
if (!is_array($tag) || !isset($tag[0])) continue; |
|
if ($tag[0] === 'title' && isset($tag[1])) $title = $tag[1]; |
|
if ($tag[0] === 'd' && isset($tag[1])) $slug = $tag[1]; |
|
if ($tag[0] === 'a' && isset($tag[1])) $a[] = $tag[1]; |
|
} |
|
return [ |
|
'title' => $title ?? ($slug ?? '(untitled)'), |
|
'slug' => $slug ?? '', |
|
'a' => $a, |
|
]; |
|
}; |
|
|
|
foreach ($slugs as $slug) { |
|
$event = $redisCache->get('magazine-' . $slug, fn() => null); |
|
if (!$event || !method_exists($event, 'getTags')) { |
|
continue; |
|
} |
|
$data = $parse($event); |
|
|
|
// Resolve categories |
|
$categories = []; |
|
foreach ($data['a'] as $coord) { |
|
if (!str_starts_with((string)$coord, '30040:')) continue; |
|
$parts = explode(':', (string)$coord, 3); |
|
if (count($parts) !== 3) continue; |
|
$catSlug = $parts[2]; |
|
$catEvent = $redisCache->get('magazine-' . $catSlug, fn() => null); |
|
if (!$catEvent || !method_exists($catEvent, 'getTags')) continue; |
|
$catData = $parse($catEvent); |
|
|
|
// Files under category from its 'a' coordinates |
|
$files = []; |
|
$repo = $em->getRepository(Article::class); |
|
foreach ($catData['a'] as $aCoord) { |
|
$partsA = explode(':', (string)$aCoord, 3); |
|
if (count($partsA) !== 3) continue; |
|
$artSlug = $partsA[2]; |
|
$authorPubkey = $partsA[1] ?? ''; |
|
$title = null; |
|
if ($artSlug !== '') { |
|
$article = $repo->findOneBy(['slug' => $artSlug]); |
|
if ($article) { $title = $article->getTitle(); } |
|
} |
|
$files[] = [ |
|
'name' => $title ?? $artSlug, |
|
'slug' => $artSlug, |
|
'coordinate' => $aCoord, |
|
'authorPubkey' => $authorPubkey, |
|
]; |
|
} |
|
|
|
$categories[] = [ |
|
'name' => $catData['title'], |
|
'slug' => $catData['slug'], |
|
'files' => $files, |
|
]; |
|
} |
|
|
|
$magazines[] = [ |
|
'name' => $data['title'], |
|
'slug' => $data['slug'], |
|
'categories' => $categories, |
|
]; |
|
} |
|
|
|
// Sort alphabetically |
|
usort($magazines, fn($a, $b) => strcmp($a['name'], $b['name'])); |
|
foreach ($magazines as &$mag) { |
|
usort($mag['categories'], fn($a, $b) => strcmp($a['name'], $b['name'])); |
|
foreach ($mag['categories'] as &$cat) { |
|
usort($cat['files'], fn($a, $b) => strcmp($a['name'], $b['name'])); |
|
} |
|
} |
|
|
|
return $this->render('admin/magazines.html.twig', [ |
|
'magazines' => $magazines, |
|
]); |
|
} |
|
}
|
|
|