Community Orte Veranstalungen
All checks were successful
Deploy / deploy (push) Successful in 57s

This commit is contained in:
2026-08-21 02:02:24 +02:00
parent a303d9ff70
commit fae2dcc830
11 changed files with 89 additions and 24 deletions

View File

@@ -182,6 +182,7 @@ final class AccountPages
$canManageProfileLevels = $communityAccess ? $communityAccess->canManageRoles($userId) : false;
$communityPointsForAccess = $community ? $community->computePoints($userId) : 0.0;
$canManageCategories = $communityAccess ? $communityAccess->canManageCategories($userId, $communityPointsForAccess) : false;
$canReviewListings = $communityAccess ? $communityAccess->canReviewListings($userId, $communityPointsForAccess) : false;
$allowedSections = ['profile', 'children', 'events', 'places', 'community', 'settings'];
if ($canManageSystemSettings) {
$allowedSections[] = 'system';
@@ -471,14 +472,28 @@ final class AccountPages
trim((string)($payload['description'] ?? '')),
trim((string)($payload['title'] ?? ''))
);
if ($action === 'event_update') {
$listingCatalog->submitUpdateRequest(
$userId,
(int)($_POST['listing_id'] ?? 0),
$payload,
(string)($_POST['moderation_reason'] ?? '')
$canDirectListingEdit = is_array($existingListing)
&& (string)($existingListing['status'] ?? '') !== 'published'
&& (
(int)($existingListing['created_by'] ?? 0) === $userId
|| $canReviewListings
);
$info = $entryKind === 'place' ? 'Änderungsanfrage für den Ort eingereicht.' : 'Änderungsanfrage für die Veranstaltung eingereicht.';
if ($action === 'event_update') {
if ($canDirectListingEdit) {
$listingCatalog->updateEditableSuggestion(
(int)($_POST['listing_id'] ?? 0),
$payload
);
$info = $entryKind === 'place' ? 'Ort aktualisiert.' : 'Veranstaltung aktualisiert.';
} else {
$listingCatalog->submitUpdateRequest(
$userId,
(int)($_POST['listing_id'] ?? 0),
$payload,
(string)($_POST['moderation_reason'] ?? '')
);
$info = $entryKind === 'place' ? 'Änderungsanfrage für den Ort eingereicht.' : 'Änderungsanfrage für die Veranstaltung eingereicht.';
}
} else {
$createdListingId = $listingCatalog->submitCreateSuggestion($userId, $payload);
$info = $entryKind === 'place' ? 'Ort zur Freigabe eingereicht.' : 'Veranstaltung zur Freigabe eingereicht.';
@@ -957,7 +972,13 @@ final class AccountPages
$editListingId = (int)$_GET['edit_listing'];
if ($editListingId > 0) {
$candidate = $listingCatalog->getMemberEntry($editListingId);
if (is_array($candidate) && (string)($candidate['status'] ?? '') === 'published') {
$canEditCandidateDirectly = is_array($candidate)
&& (string)($candidate['status'] ?? '') !== 'published'
&& (
(int)($candidate['created_by'] ?? 0) === $userId
|| $canReviewListings
);
if (is_array($candidate) && ((string)($candidate['status'] ?? '') === 'published' || $canEditCandidateDirectly)) {
$editListing = $candidate;
} else {
$error = 'Der gewünschte Eintrag ist für eine Änderungsanfrage nicht verfügbar.';
@@ -1082,6 +1103,7 @@ final class AccountPages
'communityLevelDefinitions',
'communityLevelRightDefinitions',
'communityRoles',
'canReviewListings',
'systemRoleAssignments',
'recentHighLevelUsers',
'recentHighLevelThresholdLabel',

View File

@@ -86,10 +86,7 @@ final class CommunityAccess
public function canReviewListings(int $userId, ?float $points = null): bool
{
if ($this->hasRole($userId, 'owner')) {
return false;
}
if ($this->hasRole($userId, 'site_admin') || $this->hasRole($userId, 'forum_admin')) {
if ($this->hasRole($userId, 'owner') || $this->hasRole($userId, 'site_admin') || $this->hasRole($userId, 'forum_admin')) {
return true;
}

View File

@@ -649,7 +649,7 @@ final class ListingCatalog
{
$this->ensureSchema();
$stmt = $this->pdo->prepare(
'SELECT l.*, lp.title AS place_title, lp.description AS place_description, lp.street, lp.zip, lp.city, lp.region, lp.lat, lp.lng, lp.place_kind, lp.phone, lp.website_url, lp.opening_hours_note, lp.opening_hours_json,
'SELECT l.*, lp.status AS place_status, lp.title AS place_title, lp.description AS place_description, lp.street, lp.zip, lp.city, lp.region, lp.lat, lp.lng, lp.place_kind, lp.phone, lp.website_url, lp.opening_hours_note, lp.opening_hours_json,
lo.id AS occurrence_id, lo.starts_at, lo.ends_at, lo.occurrence_type,
lo.recurrence_rule, lo.recurrence_until, lo.capacity_total,
lc.slug AS category_slug
@@ -850,6 +850,27 @@ final class ListingCatalog
return $this->createModerationRequest($listingId, 'delete', $userId, $reason, null);
}
public function updateEditableSuggestion(int $listingId, array $data): void
{
$this->ensureSchema();
$entry = $this->getMemberEntry($listingId);
if (!$entry) {
throw new \RuntimeException('Eintrag nicht gefunden.');
}
$listingStatus = (string)($entry['status'] ?? 'draft');
if ($listingStatus === 'published') {
throw new \RuntimeException('Veröffentlichte Einträge dürfen nicht direkt überschrieben werden.');
}
$placeStatus = (string)($entry['place_status'] ?? 'draft');
$normalizedListingStatus = in_array($listingStatus, ['draft', 'archived'], true) ? $listingStatus : 'draft';
$normalizedPlaceStatus = in_array($placeStatus, ['draft', 'archived'], true) ? $placeStatus : $normalizedListingStatus;
$this->assertNoDuplicateEntry($data, $listingId);
$this->saveDashboardEntry((int)($entry['created_by'] ?? 0), $data, $listingId, $normalizedListingStatus, $normalizedPlaceStatus);
}
public function listOpenModerationRequests(): array
{
$this->ensureSchema();