<?php
namespace App\Controller\Frontend;
use App\Application\Artikel\ArtikelFrontendData;
use App\Application\Artikel\ArtikelService;
use App\Application\Artikel\ArtikelServiceQuery;
use App\Entity\Artikel\Artikel;
use App\Entity\Artikel\ArtikelTyp;
use App\Form\Abo\AbonnentLoginType;
use Psr\Cache\CacheItemPoolInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route(path: '/artikel')]
#[Cache(expires: '+10 minutes')]
class ArtikelController extends AbstractController
{
#[Route(path: '/', name: 'fe.artikel_liste')]
public function liste(Request $request, ArtikelService $artikelService): Response
{
// Validierung aller möglichen URL-Parameter sonst Fehler (Page- und ApiClientCache Cache Schutz)
if (($urlParams = array_keys($request->query->all())) && ($diff_ = array_diff($urlParams, ['pg']))) {
throw $this->createNotFoundException(sprintf('Nicht konfigurierte URL Parameter abgesetzt: %s', implode(',', $diff_)));
}
// Ende
// --- Artikel ---
$pageSize = 12;
$pageNumber = $request->query->getInt('pg', 1);
if ($pageNumber === 1) {
++$pageSize;
}
$query = new ArtikelServiceQuery($pageSize, $pageNumber, false);
$query->addFilterOneOfTypOnly([ArtikelTyp::ID_AT_1, ArtikelTyp::ID_AT_3, ArtikelTyp::ID_AT_4]);
$query->addFilterOneOfStatusOnly(['publiziert']);
$query->addSort('publish_at', 'desc');
$artikels = $artikelService->findArtikels(new ArtikelFrontendData(), $query);
// --- End Artikel ---
$paging = [
'page_size' => $query->getPageSize(),
'page_curr' => $query->getPageNr(),
'page_prev' => $query->getPageNr() == 1 ? null : $query->getPageNr() - 1,
'page_next' => $query->getPageNextExist() ? $query->getPageNr() + 1 : null,
];
return $this->render('frontend/artikel/liste.html.twig', [
'h1_titel' => '',
'artikels' => $artikels,
'paging' => $paging,
]);
}
#[Route(path: '/rss.xml', name: 'fe.artikel_rss')]
public function rss(ArtikelService $artikelService, CacheItemPoolInterface $cacheApp): Response
{
$artikels = [];
$pageSize = 20;
$cachedArtikels = $cacheApp->getItem('rss_artikels');
if (!$cachedArtikels->isHit()) {
$query = new ArtikelServiceQuery($pageSize, 1, false);
$query->addFilterOneOfStatusOnly(['publiziert']);
$query->addSort('publish_at', 'desc');
$data = $artikelService->findArtikels(new ArtikelFrontendData(), $query);
foreach ($data as $artikel) {
$image = [];
if ($artikel['images']) {
$imageFilePath = $artikel['images']->current()->getFilepath();
if (file_exists($imageFilePath)) {
$image = [
'asset_path' => $artikel['images']->current()->getAssetFilepath(),
'length' => filesize($imageFilePath),
'type' => image_type_to_mime_type(\exif_imagetype($imageFilePath)),
];
}
}
$artikels[] = [
'titel' => $artikel['titel'],
'lead' => $artikel['lead'],
'publish_at' => $artikel['publish_at']->format(DATE_RSS),
'slug' => $artikel['slug'],
'guid' => $artikel['id'],
'image' => $image,
];
}
// save to cache
$cachedArtikels->set($artikels);
$expireDate = new \DateTime('+30 minutes');
$cachedArtikels->expiresAt($expireDate);
$cacheApp->save($cachedArtikels);
// end
} else {
$artikels = $cachedArtikels->get();
}
$response = $this->render('frontend/artikel/rss.xml.twig', [
'artikels' => $artikels,
]);
$response->headers->set('Content-Type', 'application/rss+xml');
return $response;
}
#[Route(path: '/{slug}', name: 'fe.artikel_detail')]
public function artikel(Request $request, $slug, ArtikelService $artikelService): Response
{
$abonnentLoginForm = null;
$redaktorPreview = false;
if ($this->isGranted('MODULE_ARTIKEL')) {
$redaktorPreview = true; // Artikel holen, auch wenn nicht publiziert
}
$artikel = $artikelService->getFrontendArtikelBySlug($slug, new ArtikelFrontendData(), $redaktorPreview);
if (!$artikel) {
throw $this->createNotFoundException();
}
// View Template bestimmen
$twigTemplate = 'frontend/artikel/artikel.html.twig';
if ($artikel['typ']->isUWPlus()) {
$twigTemplate = 'frontend/artikel/artikel-uw-plus.html.twig';
// In diesem Template das Loginform dazu generieren!
$abonnentLoginForm = $this->createForm(AbonnentLoginType::class, ['http_referer' => $request->getRequestUri()], ['csrf_protection' => false]);
} elseif ($artikel['typ']->isPublireportage()) {
$twigTemplate = 'frontend/artikel/artikel-publireportage.html.twig';
}
// End
$response = $this->render($twigTemplate, [
'abonnentLoginForm' => $abonnentLoginForm instanceof \Symfony\Component\Form\FormInterface ? $abonnentLoginForm->createView() : null,
'artikel' => $artikel,
]);
if ($artikel['typ']->isUWPlus()) {
// Explizit Cache deaktivieren, damit Paywall Logik einwandfrei funktioniert (einfachste Lösung)
$response->setMaxAge(0);
$response->setSharedMaxAge(0);
}
return $response;
}
#[Route(path: '/legacy-redirector/{slug}')]
public function legacyRedirector(ArtikelService $artikelService, $slug): RedirectResponse
{
// Versuche den Post zu finden
try {
$slug = Artikel::extractUrlSlug($slug);
$artikel = $artikelService->getFrontendArtikelBySlug($slug, new ArtikelFrontendData());
if ($artikel) {
return $this->redirectToRoute('fe.artikel_detail', [
'slug' => $artikel['slug'],
], 301);
}
} catch (\Exception $e) {
throw $e;
}
throw $this->createNotFoundException();
}
}