added date selection and filter popup
This commit is contained in:
1 parent
739a1eee28
commit
36ed3880e8
16 files changed
+741
-180
No files matched your search
@@ -56,7 +56,7 @@ class EventRepository extends ServiceEntityRepository
|
||||
*/
|
||||
public function distancesWithinRadius(float $lat, float $lon, float $radiusKm, int $limit = 500): array
|
||||
{
|
||||
// end_date comparison mirrors notEnded()/filterByWhen(): day-level
|
||||
// end_date comparison mirrors notEnded()/filterByDateRange(): day-level
|
||||
// lexicographic comparison against the raw ISO-ish string column,
|
||||
// in Europe/Berlin — this is raw SQL (DBAL, not the QueryBuilder),
|
||||
// so it can't just call that helper directly.
|
||||
@@ -124,7 +124,7 @@ class EventRepository extends ServiceEntityRepository
|
||||
*
|
||||
* @return Event[]
|
||||
*/
|
||||
public function search(?string $q, ?string $category, string $when, int $limit, int $offset, ?array $locationIds = null, string $sort = 'soonest'): array
|
||||
public function search(?string $q, ?string $category, ?string $dateFrom, ?string $dateTo, int $limit, int $offset, ?array $locationIds = null, string $sort = 'soonest'): array
|
||||
{
|
||||
// "Nearest" only means anything once a location narrowed the pool.
|
||||
if ('nearest' === $sort && null === $locationIds) {
|
||||
@@ -137,7 +137,7 @@ class EventRepository extends ServiceEntityRepository
|
||||
}
|
||||
|
||||
$matchingIds = array_map('intval', array_column(
|
||||
$this->baseSearchQb($q, $category, $when)
|
||||
$this->baseSearchQb($q, $category, $dateFrom, $dateTo)
|
||||
->select('e.id')
|
||||
->andWhere('e.id IN (:locationIds)')
|
||||
->setParameter('locationIds', $locationIds)
|
||||
@@ -156,7 +156,7 @@ class EventRepository extends ServiceEntityRepository
|
||||
return [];
|
||||
}
|
||||
|
||||
$qb = $this->baseSearchQb($q, $category, $when);
|
||||
$qb = $this->baseSearchQb($q, $category, $dateFrom, $dateTo);
|
||||
if (null !== $locationIds) {
|
||||
$qb->andWhere('e.id IN (:locationIds)')->setParameter('locationIds', $locationIds);
|
||||
}
|
||||
@@ -178,13 +178,13 @@ class EventRepository extends ServiceEntityRepository
|
||||
*
|
||||
* @param int[]|null $locationIds
|
||||
*/
|
||||
public function countSearch(?string $q, ?string $category, string $when, ?array $locationIds = null): int
|
||||
public function countSearch(?string $q, ?string $category, ?string $dateFrom, ?string $dateTo, ?array $locationIds = null): int
|
||||
{
|
||||
if (null !== $locationIds && !$locationIds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$qb = $this->baseSearchQb($q, $category, $when)->select('COUNT(DISTINCT e.id)');
|
||||
$qb = $this->baseSearchQb($q, $category, $dateFrom, $dateTo)->select('COUNT(DISTINCT e.id)');
|
||||
|
||||
if (null !== $locationIds) {
|
||||
$qb->andWhere('e.id IN (:locationIds)')->setParameter('locationIds', $locationIds);
|
||||
@@ -193,7 +193,7 @@ class EventRepository extends ServiceEntityRepository
|
||||
return (int) $qb->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
private function baseSearchQb(?string $q, ?string $category, string $when): QueryBuilder
|
||||
private function baseSearchQb(?string $q, ?string $category, ?string $dateFrom, ?string $dateTo): QueryBuilder
|
||||
{
|
||||
$qb = $this->notEnded($this->notDeleted());
|
||||
|
||||
@@ -203,45 +203,47 @@ class EventRepository extends ServiceEntityRepository
|
||||
}
|
||||
|
||||
$this->filterByCategory($qb, $category);
|
||||
$this->filterByWhen($qb, $when);
|
||||
$this->filterByDateRange($qb, $dateFrom, $dateTo);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* startDate is a raw ISO-8601-ish string ("2026-09-12T18:00:00+02:00"),
|
||||
* consistently formatted across the imported dataset, so a plain
|
||||
* lexicographic string comparison against a "Y-m-d" boundary sorts
|
||||
* correctly without needing to parse it as a real date/time column.
|
||||
* Keeps events that are happening at some point within the inclusive
|
||||
* day range [$dateFrom, $dateTo] ("Y-m-d", either end optional) — i.e.
|
||||
* the event overlaps the window, so a multi-day exhibition shows up
|
||||
* for any day it's running, not just the day it opened.
|
||||
*
|
||||
* start_date/end_date are raw ISO-8601-ish strings
|
||||
* ("2026-09-12T18:00:00+02:00"), consistently formatted across the
|
||||
* imported dataset, so a plain lexicographic comparison against a
|
||||
* "Y-m-d" boundary sorts correctly without parsing them as real
|
||||
* date/time columns. The upper bound compares against the *next* day
|
||||
* with "<", since "2026-09-12T18:00" > "2026-09-12" as strings.
|
||||
* Applied in SQL (not PHP, post-fetch) so it composes correctly with
|
||||
* pagination and COUNT — filtering after LIMIT/OFFSET would make the
|
||||
* page size and total count lie.
|
||||
* page size and total count lie. Undated events (blank start_date)
|
||||
* are excluded once a range is active; a blank end_date falls back to
|
||||
* the start alone.
|
||||
*/
|
||||
private function filterByWhen(QueryBuilder $qb, string $when): void
|
||||
private function filterByDateRange(QueryBuilder $qb, ?string $dateFrom, ?string $dateTo): void
|
||||
{
|
||||
if ('any' === $when) {
|
||||
if (!$dateFrom && !$dateTo) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Explicit timezone, not the container's (UTC): the imported dates
|
||||
// and the site's audience are both German-local, so "today" needs
|
||||
// to mean the German calendar day, not whatever day it happens to
|
||||
// be in UTC — those disagree for two hours after every UTC
|
||||
// midnight.
|
||||
$start = new \DateTimeImmutable('today', new \DateTimeZone('Europe/Berlin'));
|
||||
$end = match ($when) {
|
||||
'today' => $start->modify('+1 day'),
|
||||
'week' => $start->modify('+7 days'),
|
||||
default => null,
|
||||
};
|
||||
$qb->andWhere("e.startDate <> ''");
|
||||
|
||||
if (!$end) {
|
||||
return;
|
||||
if ($dateTo) {
|
||||
$dayAfterTo = (new \DateTimeImmutable($dateTo, new \DateTimeZone('Europe/Berlin')))->modify('+1 day');
|
||||
$qb->andWhere('e.startDate < :rangeToExclusive')
|
||||
->setParameter('rangeToExclusive', $dayAfterTo->format('Y-m-d'));
|
||||
}
|
||||
|
||||
$qb->andWhere('e.startDate >= :whenStart AND e.startDate < :whenEnd')
|
||||
->setParameter('whenStart', $start->format('Y-m-d'))
|
||||
->setParameter('whenEnd', $end->format('Y-m-d'));
|
||||
if ($dateFrom) {
|
||||
$qb->andWhere("e.endDate >= :rangeFrom OR (e.endDate = '' AND e.startDate >= :rangeFrom)")
|
||||
->setParameter('rangeFrom', $dateFrom);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,8 +291,8 @@ class EventRepository extends ServiceEntityRepository
|
||||
|
||||
/**
|
||||
* Hides events that have already ended — compared by calendar day
|
||||
* (Europe/Berlin), the same precision filterByWhen() uses for
|
||||
* "today"/"week", not exact time (end_date is a raw ISO-ish string,
|
||||
* (Europe/Berlin), the same precision filterByDateRange() uses,
|
||||
* not exact time (end_date is a raw ISO-ish string,
|
||||
* not a real date/time column). Blank end_date is treated as "still
|
||||
* current" rather than excluded, matching orderByStartDate()'s
|
||||
* defensive handling of blank date strings.
|
||||
|
||||
Reference in new issue
Block a user