From d6e6ca21fb3e307675d327f55a74fa80b4324044 Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Sat, 3 Jan 2026 01:54:11 +0100 Subject: [PATCH] asdsad --- src/App/Search.php | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/App/Search.php b/src/App/Search.php index 321ecac..2f310c5 100644 --- a/src/App/Search.php +++ b/src/App/Search.php @@ -135,12 +135,88 @@ final class Search return false; })); } + // Fallback: wenn keine Treffer, erneut ohne Token-Filter laden und nur fuzzy filtern + if (!$rows && $tokens) { + $wherePartsFallback = [ + "starts_at >= NOW()", + "status != 'cancelled'", + ]; + $bindFb = []; + $sqlFb = ''; + if ($hasGeo) { + $sqlFb = "SELECT id, title, teaser_public, description, city, region, zip, starts_at, visibility, allow_kids, location_label, lat, lng, + (6371 * ACOS(LEAST(1, + COS(RADIANS(?)) * COS(RADIANS(lat)) * COS(RADIANS(lng) - RADIANS(?)) + + SIN(RADIANS(?)) * SIN(RADIANS(lat)) + ))) AS distance_km"; + $lat = (float)$geo['lat']; + $lng = (float)$geo['lng']; + $radius = isset($geo['radius']) && is_numeric($geo['radius']) ? max(0.1, (float)$geo['radius']) : 5.0; + $latRange = $radius / 111.0; + $lngRange = $radius / (111.0 * max(0.1, cos($lat * M_PI / 180))); + $wherePartsFallback[] = "(lat IS NOT NULL AND lng IS NOT NULL)"; + $wherePartsFallback[] = "(lat BETWEEN ? AND ?)"; + $wherePartsFallback[] = "(lng BETWEEN ? AND ?)"; + $bindFb[] = $lat; + $bindFb[] = $lng; + $bindFb[] = $lat; + $bindFb[] = $lat - $latRange; + $bindFb[] = $lat + $latRange; + $bindFb[] = $lng - $lngRange; + $bindFb[] = $lng + $lngRange; + $bindFb[] = $radius; + $havingFb = true; + } else { + $sqlFb = "SELECT id, title, teaser_public, description, city, region, zip, starts_at, visibility, allow_kids, location_label, lat, lng, 1 AS distance_km"; + $havingFb = false; + } + $whereFb = $wherePartsFallback ? ('WHERE ' . implode(' AND ', $wherePartsFallback)) : ''; + $sqlFb .= " FROM events $whereFb"; + if ($havingFb) { + $sqlFb .= " HAVING distance_km <= ?"; + $sqlFb .= " ORDER BY distance_km ASC, starts_at ASC"; + } else { + $sqlFb .= " ORDER BY starts_at ASC"; + } + $sqlFb .= " LIMIT {$limit}"; + $stmtFb = $this->pdo->prepare($sqlFb); + $stmtFb->execute($bindFb); + $rowsFb = $stmtFb->fetchAll(\PDO::FETCH_ASSOC) ?: []; + if ($rowsFb) { + $rows = array_values(array_filter($rowsFb, function ($row) use ($tokens) { + $haystack = strtolower( + ($row['title'] ?? '') . ' ' . + ($row['teaser_public'] ?? '') . ' ' . + ($row['description'] ?? '') . ' ' . + ($row['city'] ?? '') . ' ' . + ($row['region'] ?? '') + ); + $words = preg_split('/[^a-z0-9äöüß]+/i', $haystack) ?: []; + foreach ($tokens as $tok) { + $t = strtolower($tok); + if ($t === '') continue; + if (str_contains($haystack, $t)) { + return true; + } + foreach ($words as $w) { + if ($w === '') continue; + $dist = levenshtein($t, $w); + if ($dist <= 1 || ($dist <= 2 && max(strlen($t), strlen($w)) > 4)) { + return true; + } + } + } + return false; + })); + } + } if (defined('APP_ENV') && APP_ENV === 'staging') { $logOk = [ 'status' => 'ok', 'sql' => $sql, 'bind' => $bind, 'count' => count($rows), + 'fallback' => ($rows ? 'primary' : 'fallback'), ]; @file_put_contents(__DIR__ . '/../../debug/search_debug.log', print_r($logOk, true)); }