|
|
|
@ -5,9 +5,11 @@ declare(strict_types=1); |
|
|
|
namespace App\Controller; |
|
|
|
namespace App\Controller; |
|
|
|
|
|
|
|
|
|
|
|
use App\Repository\ArticleRepository; |
|
|
|
use App\Repository\ArticleRepository; |
|
|
|
|
|
|
|
use App\Service\NostrClient; |
|
|
|
use Exception; |
|
|
|
use Exception; |
|
|
|
use Psr\Cache\InvalidArgumentException; |
|
|
|
use Psr\Cache\InvalidArgumentException; |
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
|
|
|
|
|
|
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; |
|
|
|
use Symfony\Component\HttpFoundation\RequestStack; |
|
|
|
use Symfony\Component\HttpFoundation\RequestStack; |
|
|
|
use Symfony\Component\HttpFoundation\Response; |
|
|
|
use Symfony\Component\HttpFoundation\Response; |
|
|
|
use Symfony\Component\Routing\Attribute\Route; |
|
|
|
use Symfony\Component\Routing\Attribute\Route; |
|
|
|
@ -17,9 +19,10 @@ use Psr\Log\LoggerInterface; |
|
|
|
class DefaultController extends AbstractController |
|
|
|
class DefaultController extends AbstractController |
|
|
|
{ |
|
|
|
{ |
|
|
|
public function __construct( |
|
|
|
public function __construct( |
|
|
|
private readonly CacheInterface $redisCache) |
|
|
|
private readonly CacheInterface $cache, |
|
|
|
{ |
|
|
|
private readonly NostrClient $nostrClient, |
|
|
|
} |
|
|
|
private readonly ParameterBagInterface $params |
|
|
|
|
|
|
|
) {} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* @throws Exception |
|
|
|
* @throws Exception |
|
|
|
@ -28,9 +31,12 @@ class DefaultController extends AbstractController |
|
|
|
#[Route('/', name: 'home')] |
|
|
|
#[Route('/', name: 'home')] |
|
|
|
public function index(): Response |
|
|
|
public function index(): Response |
|
|
|
{ |
|
|
|
{ |
|
|
|
// get newsroom index, loop over categories, pick top three from each and display in sections |
|
|
|
$npub = $this->params->get('npub'); |
|
|
|
$mag = $this->redisCache->get('magazine-newsroom-magazine-by-newsroom', function (){ |
|
|
|
$dTag = $this->params->get('d_tag'); |
|
|
|
return null; |
|
|
|
$cacheKey = 'magazine-' . $dTag; |
|
|
|
|
|
|
|
$mag = $this->cache->get($cacheKey, function ($item) use ($npub, $dTag) { |
|
|
|
|
|
|
|
$item->expiresAfter(300); // 5 minutes |
|
|
|
|
|
|
|
return $this->nostrClient->getMagazineIndex($npub, $dTag); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Handle case when magazine is not found |
|
|
|
// Handle case when magazine is not found |
|
|
|
@ -56,52 +62,45 @@ class DefaultController extends AbstractController |
|
|
|
* @throws InvalidArgumentException |
|
|
|
* @throws InvalidArgumentException |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#[Route('/cat/{slug}', name: 'magazine-category')] |
|
|
|
#[Route('/cat/{slug}', name: 'magazine-category')] |
|
|
|
public function magCategory($slug, CacheInterface $redisCache, |
|
|
|
public function magCategory($slug, ArticleRepository $articleRepository, LoggerInterface $logger): Response |
|
|
|
ArticleRepository $articleRepository, |
|
|
|
|
|
|
|
LoggerInterface $logger): Response |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
$catIndex = $redisCache->get('magazine-' . $slug, function (){ |
|
|
|
$npub = $this->params->get('npub'); |
|
|
|
throw new Exception('Not found'); |
|
|
|
$cacheKey = 'magazine-' . $slug; |
|
|
|
|
|
|
|
$catIndex = $this->cache->get($cacheKey, function ($item) use ($npub, $slug) { |
|
|
|
|
|
|
|
$item->expiresAfter(300); // 5 minutes |
|
|
|
|
|
|
|
return $this->nostrClient->getMagazineIndex($npub, $slug); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
$list = []; |
|
|
|
$list = []; |
|
|
|
$coordinates = []; // Store full coordinates (kind:author:slug) |
|
|
|
$coordinates = []; |
|
|
|
$category = []; |
|
|
|
$category = []; |
|
|
|
|
|
|
|
if ($catIndex) { |
|
|
|
// Extract category metadata and article coordinates |
|
|
|
foreach ($catIndex->getTags() as $tag) { |
|
|
|
foreach ($catIndex->getTags() as $tag) { |
|
|
|
if ($tag[0] === 'title') { |
|
|
|
if ($tag[0] === 'title') { |
|
|
|
$category['title'] = $tag[1]; |
|
|
|
$category['title'] = $tag[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
if ($tag[0] === 'summary') { |
|
|
|
if ($tag[0] === 'summary') { |
|
|
|
$category['summary'] = $tag[1]; |
|
|
|
$category['summary'] = $tag[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
if ($tag[0] === 'a') { |
|
|
|
if ($tag[0] === 'a') { |
|
|
|
$coordinates[] = $tag[1]; |
|
|
|
$coordinates[] = $tag[1]; // Store the full coordinate |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!empty($coordinates)) { |
|
|
|
if (!empty($coordinates)) { |
|
|
|
// Extract slugs for database query |
|
|
|
|
|
|
|
$slugs = array_map(function($coordinate) { |
|
|
|
$slugs = array_map(function($coordinate) { |
|
|
|
$parts = explode(':', $coordinate, 3); |
|
|
|
$parts = explode(':', $coordinate, 3); |
|
|
|
return end($parts); |
|
|
|
return end($parts); |
|
|
|
}, $coordinates); |
|
|
|
}, $coordinates); |
|
|
|
$slugs = array_filter($slugs); // Remove empty values |
|
|
|
$slugs = array_filter($slugs); |
|
|
|
|
|
|
|
|
|
|
|
// Use database query instead of Elasticsearch |
|
|
|
|
|
|
|
$articles = $articleRepository->findBySlugsCriteria($slugs); |
|
|
|
$articles = $articleRepository->findBySlugsCriteria($slugs); |
|
|
|
|
|
|
|
|
|
|
|
// Create a map of slug => item to remove duplicates |
|
|
|
|
|
|
|
$slugMap = []; |
|
|
|
$slugMap = []; |
|
|
|
foreach ($articles as $item) { |
|
|
|
foreach ($articles as $item) { |
|
|
|
$slug = $item->getSlug(); |
|
|
|
$slug = $item->getSlug(); |
|
|
|
if ($slug !== '') { |
|
|
|
if ($slug !== '') { |
|
|
|
// If the slugMap doesn't contain it yet, add it |
|
|
|
|
|
|
|
if (!isset($slugMap[$slug])) { |
|
|
|
if (!isset($slugMap[$slug])) { |
|
|
|
$slugMap[$slug] = $item; |
|
|
|
$slugMap[$slug] = $item; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// If it already exists, compare created_at timestamps and save newest |
|
|
|
|
|
|
|
$existingItem = $slugMap[$slug]; |
|
|
|
$existingItem = $slugMap[$slug]; |
|
|
|
if ($item->getCreatedAt() > $existingItem->getCreatedAt()) { |
|
|
|
if ($item->getCreatedAt() > $existingItem->getCreatedAt()) { |
|
|
|
$slugMap[$slug] = $item; |
|
|
|
$slugMap[$slug] = $item; |
|
|
|
@ -109,25 +108,6 @@ class DefaultController extends AbstractController |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Find missing coordinates |
|
|
|
|
|
|
|
$missingCoordinates = []; |
|
|
|
|
|
|
|
foreach ($coordinates as $coordinate) { |
|
|
|
|
|
|
|
$parts = explode(':', $coordinate, 3); |
|
|
|
|
|
|
|
if (!isset($slugMap[end($parts)])) { |
|
|
|
|
|
|
|
$missingCoordinates[] = $coordinate; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If we have missing articles, log them for now |
|
|
|
|
|
|
|
if (!empty($missingCoordinates)) { |
|
|
|
|
|
|
|
$logger->info('There were missing articles', [ |
|
|
|
|
|
|
|
'missing' => $missingCoordinates |
|
|
|
|
|
|
|
]); |
|
|
|
|
|
|
|
// Note: Removed NostrClient fetching logic for simplification |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Build ordered list based on original coordinates order |
|
|
|
|
|
|
|
foreach ($coordinates as $coordinate) { |
|
|
|
foreach ($coordinates as $coordinate) { |
|
|
|
$parts = explode(':', $coordinate, 3); |
|
|
|
$parts = explode(':', $coordinate, 3); |
|
|
|
if (isset($slugMap[end($parts)])) { |
|
|
|
if (isset($slugMap[end($parts)])) { |
|
|
|
|