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]) : '[]', ]); } }