This commit is contained in:
@@ -454,14 +454,51 @@ final class AccountPages
|
||||
$existingEvent = $stmt?->fetch(\PDO::FETCH_ASSOC) ?: null;
|
||||
}
|
||||
}
|
||||
$imagePath = self::storeUploadedImage($_FILES['image_file'] ?? null, is_array($existingEvent) ? (string)($existingEvent['image_path'] ?? '') : '');
|
||||
$allowKids = ((string)($_POST['with_children'] ?? 'yes')) === 'yes' ? 1 : 0;
|
||||
$capacity = isset($_POST['max_participants']) && $_POST['max_participants'] !== '' ? (int)$_POST['max_participants'] : null;
|
||||
$eventStartValue = self::normalizeDateForStorage((string)($_POST['starts_at'] ?? ''), true);
|
||||
$sourceMode = (string)($_POST['event_location_mode'] ?? 'custom');
|
||||
$sourceListingId = isset($_POST['event_location_source_id']) && $_POST['event_location_source_id'] !== '' ? (int)$_POST['event_location_source_id'] : null;
|
||||
$locationLabel = null;
|
||||
$street = trim((string)($_POST['street'] ?? ''));
|
||||
$zip = trim((string)($_POST['zip'] ?? ''));
|
||||
$city = trim((string)($_POST['city'] ?? ''));
|
||||
$region = trim((string)($_POST['region'] ?? ''));
|
||||
$lat = isset($_POST['lat']) && $_POST['lat'] !== '' ? (float)$_POST['lat'] : null;
|
||||
$lng = isset($_POST['lng']) && $_POST['lng'] !== '' ? (float)$_POST['lng'] : null;
|
||||
$hasAddress = $street !== '' || $zip !== '' || $city !== '' || $region !== '';
|
||||
if ($hasAddress) {
|
||||
$categoryInput = trim((string)($_POST['category_input'] ?? $_POST['category_slug'] ?? ''));
|
||||
$categorySlug = '';
|
||||
$sourceListing = null;
|
||||
if (in_array($sourceMode, ['place', 'editorial_event'], true)) {
|
||||
if (!$listingCatalog || $sourceListingId === null || $sourceListingId <= 0) {
|
||||
throw new \RuntimeException('Bitte wähle einen gültigen Ort oder eine gültige Veranstaltung aus der Datenbank.');
|
||||
}
|
||||
$sourceListing = $listingCatalog->getEventLocationSource($sourceListingId);
|
||||
if (!$sourceListing || (string)($sourceListing['listing_type'] ?? '') !== $sourceMode) {
|
||||
throw new \RuntimeException('Die gewählte Location ist nicht verfügbar.');
|
||||
}
|
||||
if ($sourceMode === 'editorial_event') {
|
||||
$eventDate = substr($eventStartValue, 0, 10);
|
||||
$sourceStart = !empty($sourceListing['starts_at']) ? substr((string)$sourceListing['starts_at'], 0, 10) : '';
|
||||
$sourceUntil = !empty($sourceListing['recurrence_until']) ? substr((string)$sourceListing['recurrence_until'], 0, 10) : '';
|
||||
if ($eventDate === '' || $sourceStart === '' || $sourceUntil === '' || $eventDate < $sourceStart || $eventDate > $sourceUntil) {
|
||||
throw new \RuntimeException('Die gewählte Veranstaltungs-Location passt zeitlich nicht zum Event-Datum.');
|
||||
}
|
||||
}
|
||||
$street = trim((string)($sourceListing['street'] ?? ''));
|
||||
$zip = trim((string)($sourceListing['zip'] ?? ''));
|
||||
$city = trim((string)($sourceListing['city'] ?? ''));
|
||||
$region = trim((string)($sourceListing['region'] ?? ''));
|
||||
$lat = isset($sourceListing['lat']) && $sourceListing['lat'] !== '' ? (float)$sourceListing['lat'] : null;
|
||||
$lng = isset($sourceListing['lng']) && $sourceListing['lng'] !== '' ? (float)$sourceListing['lng'] : null;
|
||||
$locationLabel = trim((string)($sourceListing['title'] ?? '')) ?: null;
|
||||
$categorySlug = trim((string)($sourceListing['category_slug'] ?? ''));
|
||||
} else {
|
||||
$hasAddress = $street !== '' || $zip !== '' || $city !== '' || $region !== '';
|
||||
if (!$hasAddress) {
|
||||
throw new \RuntimeException('Bitte gib für eine benutzerdefinierte Location eine Adresse an.');
|
||||
}
|
||||
$resolvedAddress = null;
|
||||
if ($lat !== null && $lng !== null) {
|
||||
$resolvedAddress = self::reverseGeocodeAddress($lat, $lng);
|
||||
@@ -479,21 +516,14 @@ final class AccountPages
|
||||
$region = $resolvedAddress['region'] !== '' ? $resolvedAddress['region'] : $region;
|
||||
$lat = $resolvedAddress['lat'];
|
||||
$lng = $resolvedAddress['lng'];
|
||||
if ($categoryInput !== '' && $listingCatalog) {
|
||||
$category = $listingCatalog->ensureCategoryForInput($categoryInput, 'event');
|
||||
$categorySlug = (string)($category['slug'] ?? '');
|
||||
}
|
||||
}
|
||||
$imagePath = self::storeUploadedImage($_FILES['image_file'] ?? null, is_array($existingEvent) ? (string)($existingEvent['image_path'] ?? '') : '');
|
||||
$allowKids = ((string)($_POST['with_children'] ?? 'yes')) === 'yes' ? 1 : 0;
|
||||
$capacity = isset($_POST['max_participants']) && $_POST['max_participants'] !== '' ? (int)$_POST['max_participants'] : null;
|
||||
$categoryInput = trim((string)($_POST['category_input'] ?? $_POST['category_slug'] ?? ''));
|
||||
$categorySlug = '';
|
||||
if ($categoryInput !== '' && $listingCatalog) {
|
||||
$category = $listingCatalog->ensureCategoryForInput($categoryInput, 'event');
|
||||
$categorySlug = (string)($category['slug'] ?? '');
|
||||
}
|
||||
|
||||
$eventStartValue = self::normalizeDateForStorage((string)($_POST['starts_at'] ?? ''), true);
|
||||
|
||||
if ($action === 'event_add') {
|
||||
$stmt = $pdo?->prepare('INSERT INTO events (created_by, title, teaser_public, description, category_slug, image_path, location_label, street, zip, city, region, lat, lng, starts_at, max_participants, allow_kids, visibility, status, created_at, updated_at) VALUES (:uid, :title, :teaser, :descr, :categorySlug, :imagePath, :loc, :street, :zip, :city, :region, :lat, :lng, :start, :capacity, :allow, :vis, :status, NOW(), NOW())');
|
||||
$stmt = $pdo?->prepare('INSERT INTO events (created_by, title, teaser_public, description, category_slug, image_path, location_label, location_source_type, location_source_listing_id, street, zip, city, region, lat, lng, starts_at, max_participants, allow_kids, visibility, status, created_at, updated_at) VALUES (:uid, :title, :teaser, :descr, :categorySlug, :imagePath, :loc, :sourceType, :sourceListingId, :street, :zip, :city, :region, :lat, :lng, :start, :capacity, :allow, :vis, :status, NOW(), NOW())');
|
||||
$stmt?->execute([
|
||||
'uid' => $userId,
|
||||
'title' => trim((string)$_POST['title']),
|
||||
@@ -501,7 +531,9 @@ final class AccountPages
|
||||
'descr' => trim((string)$_POST['description']),
|
||||
'categorySlug' => $categorySlug !== '' ? $categorySlug : null,
|
||||
'imagePath' => $imagePath !== '' ? $imagePath : null,
|
||||
'loc' => null,
|
||||
'loc' => $locationLabel,
|
||||
'sourceType' => $sourceMode,
|
||||
'sourceListingId' => $sourceMode === 'custom' ? null : $sourceListingId,
|
||||
'street' => $street ?: null,
|
||||
'zip' => $zip,
|
||||
'city' => $city,
|
||||
@@ -524,7 +556,7 @@ final class AccountPages
|
||||
}
|
||||
} else {
|
||||
$eventId = (int)($_POST['event_id'] ?? 0);
|
||||
$stmt = $pdo?->prepare('UPDATE events SET title=:title, teaser_public=:teaser, description=:descr, category_slug=:categorySlug, image_path=:imagePath, location_label=:loc, street=:street, zip=:zip, city=:city, region=:region, lat=:lat, lng=:lng, starts_at=:start, max_participants=:capacity, allow_kids=:allow, visibility=:vis, updated_at=NOW() WHERE id=:id AND created_by=:uid');
|
||||
$stmt = $pdo?->prepare('UPDATE events SET title=:title, teaser_public=:teaser, description=:descr, category_slug=:categorySlug, image_path=:imagePath, location_label=:loc, location_source_type=:sourceType, location_source_listing_id=:sourceListingId, street=:street, zip=:zip, city=:city, region=:region, lat=:lat, lng=:lng, starts_at=:start, max_participants=:capacity, allow_kids=:allow, visibility=:vis, updated_at=NOW() WHERE id=:id AND created_by=:uid');
|
||||
$stmt?->execute([
|
||||
'id' => $eventId,
|
||||
'uid' => $userId,
|
||||
@@ -533,7 +565,9 @@ final class AccountPages
|
||||
'descr' => trim((string)$_POST['description']),
|
||||
'categorySlug' => $categorySlug !== '' ? $categorySlug : null,
|
||||
'imagePath' => $imagePath !== '' ? $imagePath : null,
|
||||
'loc' => null,
|
||||
'loc' => $locationLabel,
|
||||
'sourceType' => $sourceMode,
|
||||
'sourceListingId' => $sourceMode === 'custom' ? null : $sourceListingId,
|
||||
'street' => $street ?: null,
|
||||
'zip' => $zip,
|
||||
'city' => $city,
|
||||
@@ -712,8 +746,9 @@ final class AccountPages
|
||||
$listingCategories = $listingCatalog ? $listingCatalog->listCategories(['general', 'place', 'food', 'event', 'family']) : [];
|
||||
$categoryReviewItems = $listingCatalog && $canManageSystemSettings ? $listingCatalog->listCategoryReviewItems() : [];
|
||||
$placeSuggestions = $listingCatalog ? $listingCatalog->listPlaceSuggestions(60) : [];
|
||||
$eventLocationOptions = $listingCatalog ? $listingCatalog->listEventLocationOptions(120) : [];
|
||||
$stmt = $pdo?->prepare(
|
||||
'SELECT e.id, e.title, e.teaser_public, e.description, e.category_slug, e.image_path, e.location_label, e.street, e.zip, e.city, e.region, e.starts_at, e.max_participants, e.allow_kids, e.visibility, e.status, e.lat, e.lng,
|
||||
'SELECT e.id, e.title, e.teaser_public, e.description, e.category_slug, e.image_path, e.location_label, e.location_source_type, e.location_source_listing_id, e.street, e.zip, e.city, e.region, e.starts_at, e.max_participants, e.allow_kids, e.visibility, e.status, e.lat, e.lng,
|
||||
(SELECT COUNT(*) FROM event_participants ep WHERE ep.event_id = e.id) AS participant_count
|
||||
FROM events e
|
||||
WHERE e.created_by = :id AND e.starts_at >= NOW()
|
||||
@@ -832,6 +867,7 @@ final class AccountPages
|
||||
'listingCategories',
|
||||
'categoryReviewItems',
|
||||
'placeSuggestions',
|
||||
'eventLocationOptions',
|
||||
'communityPoints',
|
||||
'communityLevel',
|
||||
'communityRoles',
|
||||
@@ -980,6 +1016,8 @@ final class AccountPages
|
||||
$columns = [
|
||||
'category_slug' => 'ALTER TABLE events ADD COLUMN category_slug VARCHAR(120) NULL AFTER description',
|
||||
'image_path' => 'ALTER TABLE events ADD COLUMN image_path VARCHAR(255) NULL AFTER category_slug',
|
||||
'location_source_type' => 'ALTER TABLE events ADD COLUMN location_source_type ENUM("custom","place","editorial_event") NOT NULL DEFAULT "custom" AFTER location_label',
|
||||
'location_source_listing_id' => 'ALTER TABLE events ADD COLUMN location_source_listing_id BIGINT UNSIGNED NULL AFTER location_source_type',
|
||||
];
|
||||
foreach ($columns as $column => $sql) {
|
||||
$stmt = $pdo->prepare('SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = "events" AND column_name = :column LIMIT 1');
|
||||
|
||||
@@ -493,6 +493,81 @@ final class ListingCatalog
|
||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||
}
|
||||
|
||||
public function listEventLocationOptions(int $limit = 80): array
|
||||
{
|
||||
$this->ensureSchema();
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT l.id,
|
||||
l.listing_type,
|
||||
l.title,
|
||||
l.status,
|
||||
lp.street,
|
||||
lp.zip,
|
||||
lp.city,
|
||||
lp.region,
|
||||
lp.lat,
|
||||
lp.lng,
|
||||
lp.place_kind,
|
||||
lo.starts_at,
|
||||
lo.recurrence_until,
|
||||
lc.slug AS category_slug,
|
||||
lc.title AS category_title
|
||||
FROM listings l
|
||||
LEFT JOIN listing_places lp ON lp.id = l.primary_place_id
|
||||
LEFT JOIN listing_occurrences lo ON lo.listing_id = l.id
|
||||
LEFT JOIN listing_category_map lcm ON lcm.listing_id = l.id
|
||||
LEFT JOIN listing_categories lc ON lc.id = lcm.category_id
|
||||
WHERE l.listing_type IN ("place","editorial_event")
|
||||
AND l.status IN ("draft","published")
|
||||
ORDER BY
|
||||
CASE l.listing_type
|
||||
WHEN "place" THEN 1
|
||||
WHEN "editorial_event" THEN 2
|
||||
ELSE 3
|
||||
END,
|
||||
l.title ASC,
|
||||
COALESCE(lo.starts_at, l.created_at) ASC
|
||||
LIMIT :limit'
|
||||
);
|
||||
$stmt->bindValue(':limit', max(1, min(250, $limit)), \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||
}
|
||||
|
||||
public function getEventLocationSource(int $listingId): ?array
|
||||
{
|
||||
$this->ensureSchema();
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT l.id,
|
||||
l.listing_type,
|
||||
l.title,
|
||||
l.status,
|
||||
lp.street,
|
||||
lp.zip,
|
||||
lp.city,
|
||||
lp.region,
|
||||
lp.lat,
|
||||
lp.lng,
|
||||
lp.place_kind,
|
||||
lo.starts_at,
|
||||
lo.recurrence_until,
|
||||
lc.slug AS category_slug,
|
||||
lc.title AS category_title
|
||||
FROM listings l
|
||||
LEFT JOIN listing_places lp ON lp.id = l.primary_place_id
|
||||
LEFT JOIN listing_occurrences lo ON lo.listing_id = l.id
|
||||
LEFT JOIN listing_category_map lcm ON lcm.listing_id = l.id
|
||||
LEFT JOIN listing_categories lc ON lc.id = lcm.category_id
|
||||
WHERE l.id = :id
|
||||
AND l.listing_type IN ("place","editorial_event")
|
||||
AND l.status IN ("draft","published")
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt->execute(['id' => $listingId]);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
public function listUserOpenModerationRequestMap(int $userId): array
|
||||
{
|
||||
$this->ensureSchema();
|
||||
|
||||
Reference in New Issue
Block a user