111 lines
4.5 KiB
PHP
111 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Repository\CategoryRepository;
|
|
use App\Repository\EventRepository;
|
|
use App\Service\EventMapSerializer;
|
|
use App\Service\RangeDefaults;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
|
|
class EventController extends AbstractController
|
|
{
|
|
private const PER_PAGE = 24;
|
|
private const SORTS = ['soonest', 'nearest', 'az', 'za'];
|
|
|
|
// Browse events and the old standalone /search page did the same job
|
|
// (text/category/when/location filtering over the same event set) —
|
|
// merged here rather than kept as two near-duplicate controllers.
|
|
#[Route('/events', name: 'event_list')]
|
|
public function list(Request $request, EventRepository $events, CategoryRepository $categories): Response
|
|
{
|
|
$q = trim((string) $request->query->get('q', ''));
|
|
$category = $request->query->get('category') ?: null;
|
|
$when = $request->query->get('when') ?: 'any';
|
|
$page = max(1, $request->query->getInt('page', 1));
|
|
|
|
// Location filtering is opt-in — plain text/category browsing
|
|
// behaves exactly as before unless a place/"use my location"
|
|
// actually set lat/lon.
|
|
$latParam = $request->query->get('lat');
|
|
$lonParam = $request->query->get('lon');
|
|
$hasLocation = null !== $latParam && null !== $lonParam && '' !== $latParam && '' !== $lonParam;
|
|
$lat = $hasLocation ? (float) $latParam : null;
|
|
$lon = $hasLocation ? (float) $lonParam : null;
|
|
|
|
$rangeKm = (int) $request->query->get('range', RangeDefaults::DEFAULT_KM);
|
|
if ($rangeKm <= 0 || $rangeKm > RangeDefaults::MAX_KM) {
|
|
$rangeKm = RangeDefaults::DEFAULT_KM;
|
|
}
|
|
|
|
$distances = [];
|
|
$locationIds = null;
|
|
if ($hasLocation) {
|
|
$distances = $events->distancesWithinRadius($lat, $lon, $rangeKm, 3000);
|
|
$locationIds = array_keys($distances);
|
|
}
|
|
|
|
// "Nearest" only means anything with a location active — default to
|
|
// it there (matches this page's previous, sort-less behavior),
|
|
// otherwise fall back to chronological.
|
|
$defaultSort = $hasLocation ? 'nearest' : 'soonest';
|
|
$sort = $request->query->get('sort') ?: $defaultSort;
|
|
if (!\in_array($sort, self::SORTS, true)) {
|
|
$sort = $defaultSort;
|
|
}
|
|
|
|
$offset = ($page - 1) * self::PER_PAGE;
|
|
$items = $events->search($q ?: null, $category, $when, self::PER_PAGE, $offset, $locationIds, $sort);
|
|
$total = $events->countSearch($q ?: null, $category, $when, $locationIds);
|
|
|
|
return $this->render('events/list.html.twig', [
|
|
'activeNav' => 'events',
|
|
'events' => $items,
|
|
'categories' => $categories->findUsedNames(),
|
|
'activeCategory' => $category,
|
|
'q' => $q,
|
|
'when' => $when,
|
|
'hasLocation' => $hasLocation,
|
|
'lat' => $lat,
|
|
'lon' => $lon,
|
|
'rangeKm' => $rangeKm,
|
|
'rangeOptions' => RangeDefaults::OPTIONS_KM,
|
|
'distances' => $distances,
|
|
'sort' => $sort,
|
|
// Other active filters, ready to |merge with a one-field
|
|
// override in a link — e.g. filters|merge({category: 'Markt'})
|
|
// keeps q/when/location while only changing the category.
|
|
'filters' => [
|
|
'q' => $q ?: null,
|
|
'category' => $category,
|
|
'when' => 'any' !== $when ? $when : null,
|
|
'lat' => $hasLocation ? $lat : null,
|
|
'lon' => $hasLocation ? $lon : null,
|
|
'range' => $hasLocation ? $rangeKm : null,
|
|
'sort' => $sort !== $defaultSort ? $sort : null,
|
|
],
|
|
'page' => $page,
|
|
'totalPages' => max(1, (int) ceil($total / self::PER_PAGE)),
|
|
'total' => $total,
|
|
]);
|
|
}
|
|
|
|
#[Route('/events/{id}', name: 'event_show', requirements: ['id' => '\d+'])]
|
|
public function show(int $id, EventRepository $events, EventMapSerializer $mapSerializer): Response
|
|
{
|
|
$event = $events->findOneNotDeleted($id);
|
|
if (!$event) {
|
|
throw $this->createNotFoundException('Event nicht gefunden.');
|
|
}
|
|
|
|
return $this->render('events/show.html.twig', [
|
|
'activeNav' => 'events',
|
|
'event' => $event,
|
|
'mapEventJson' => $event->hasCoordinates() ? $mapSerializer->toJson([$event]) : '[]',
|
|
]);
|
|
}
|
|
}
|