This commit is contained in:
@@ -29,6 +29,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
|
|||||||
- Orte und Veranstaltungen sind vorerst in einen separaten Mitgliederbereichspunkt `Orte & Veranstaltungen` verschoben.
|
- Orte und Veranstaltungen sind vorerst in einen separaten Mitgliederbereichspunkt `Orte & Veranstaltungen` verschoben.
|
||||||
- In `Orte & Veranstaltungen` können Nutzer dauerhafte Orte und zeitlich begrenzte Veranstaltungen neu anlegen.
|
- In `Orte & Veranstaltungen` können Nutzer dauerhafte Orte und zeitlich begrenzte Veranstaltungen neu anlegen.
|
||||||
- Neue Orte und Veranstaltungen bleiben bis zur Freigabe im Status `wartet auf Freigabe` und werden erst danach systemweit veröffentlicht.
|
- Neue Orte und Veranstaltungen bleiben bis zur Freigabe im Status `wartet auf Freigabe` und werden erst danach systemweit veröffentlicht.
|
||||||
|
- Noch nicht veröffentlichte Orts- und Veranstaltungsvorschläge können vom Ersteller im Mitgliederbereich direkt weiterbearbeitet werden.
|
||||||
- Änderungs- und Löschwünsche für veröffentlichte Orte und Veranstaltungen laufen immer über eine begründete Moderationsanfrage.
|
- Änderungs- und Löschwünsche für veröffentlichte Orte und Veranstaltungen laufen immer über eine begründete Moderationsanfrage.
|
||||||
- Vorschläge für neue Orte und Veranstaltungen dürfen schon vor der Freigabe als Ortsvorschlag für Events genutzt werden, solange sie noch offen geprüft werden.
|
- Vorschläge für neue Orte und Veranstaltungen dürfen schon vor der Freigabe als Ortsvorschlag für Events genutzt werden, solange sie noch offen geprüft werden.
|
||||||
- Dubletten bei Orten und Veranstaltungen sollen serverseitig mindestens über Namen und Adresse abgefangen werden.
|
- Dubletten bei Orten und Veranstaltungen sollen serverseitig mindestens über Namen und Adresse abgefangen werden.
|
||||||
@@ -50,6 +51,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
|
|||||||
- In `Profil-Levels` gibt es zusätzlich eine Liste von Nutzern, die in den letzten 30 Tagen mindestens den Rang `Säule der Väter-Community` erreicht haben.
|
- In `Profil-Levels` gibt es zusätzlich eine Liste von Nutzern, die in den letzten 30 Tagen mindestens den Rang `Säule der Väter-Community` erreicht haben.
|
||||||
- System-Level bleiben getrennt als Rollen `Forum-Admin`, `Site-Admin` und `SiteOwner`.
|
- System-Level bleiben getrennt als Rollen `Forum-Admin`, `Site-Admin` und `SiteOwner`.
|
||||||
- `Forum-Admin` kann Kategorien bereits bestätigen und zusammenführen sowie Orte und Veranstaltungen freigeben.
|
- `Forum-Admin` kann Kategorien bereits bestätigen und zusammenführen sowie Orte und Veranstaltungen freigeben.
|
||||||
|
- `SiteOwner` und `Site-Admin` erben diese Freigaberechte vollständig mit.
|
||||||
- Die Vergabe von System-Leveln läuft im Bereich `Community-Admin` jetzt über eine Benutzersuche statt über rohe Benutzer-IDs; `Site-Admins` bleiben auf die bestehende Rollenlogik begrenzt.
|
- Die Vergabe von System-Leveln läuft im Bereich `Community-Admin` jetzt über eine Benutzersuche statt über rohe Benutzer-IDs; `Site-Admins` bleiben auf die bestehende Rollenlogik begrenzt.
|
||||||
- Kategorien liegen nicht mehr unter `System`, sondern in einem eigenen Mitgliederbereichspunkt `Kategorien`; dort werden nur neue Kategorien angezeigt und per Vorschlagsfeld mit bestehenden Kategorien aus der Datenbank zusammengeführt.
|
- Kategorien liegen nicht mehr unter `System`, sondern in einem eigenen Mitgliederbereichspunkt `Kategorien`; dort werden nur neue Kategorien angezeigt und per Vorschlagsfeld mit bestehenden Kategorien aus der Datenbank zusammengeführt.
|
||||||
- Neue Kategorien bleiben dort sichtbar, bis sie von einem Berechtigten bestätigt oder mit einer bestehenden Kategorie zusammengeführt werden.
|
- Neue Kategorien bleiben dort sichtbar, bis sie von einem Berechtigten bestätigt oder mit einer bestehenden Kategorie zusammengeführt werden.
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ Stand: 2026-08-10
|
|||||||
- Community-Level-Rechte für Kategorien und Orts-/Veranstaltungsfreigaben: `config/community.php`, `src/App/Community.php`, `src/App/CommunityAccess.php`, `partials/landing/account/community-admin.php`
|
- Community-Level-Rechte für Kategorien und Orts-/Veranstaltungsfreigaben: `config/community.php`, `src/App/Community.php`, `src/App/CommunityAccess.php`, `partials/landing/account/community-admin.php`
|
||||||
- Preis-, Bild- und Ortseingabe für Orte und Veranstaltungen sowie reduzierte Event-Maske: `partials/landing/account/dashboard.php` plus Speicherung in `src/App/ListingCatalog.php`
|
- Preis-, Bild- und Ortseingabe für Orte und Veranstaltungen sowie reduzierte Event-Maske: `partials/landing/account/dashboard.php` plus Speicherung in `src/App/ListingCatalog.php`
|
||||||
- Freigaben sowie Änderungs- und Löschanfragen für Orte und Veranstaltungen: `src/App/ListingCatalog.php`, `partials/landing/account/dashboard.php`, `partials/landing/account/community-admin.php`
|
- Freigaben sowie Änderungs- und Löschanfragen für Orte und Veranstaltungen: `src/App/ListingCatalog.php`, `partials/landing/account/dashboard.php`, `partials/landing/account/community-admin.php`
|
||||||
|
- Direktbearbeitung noch nicht veröffentlichter Orts- und Veranstaltungsvorschläge sowie Rechteauflösung für deren Freigabe: `src/App/CommunityAccess.php`, `src/App/AccountPages.php`, `src/App/ListingCatalog.php`, `partials/landing/account/dashboard.php`
|
||||||
- Rollenvergabe per Benutzersuche im Community-Admin: `partials/landing/account/community-admin.php`, `src/App/CommunityAccess.php`
|
- Rollenvergabe per Benutzersuche im Community-Admin: `partials/landing/account/community-admin.php`, `src/App/CommunityAccess.php`
|
||||||
- Legacy-Eigen-Events wurden erweitert in `src/App/AccountPages.php` und `Internal/db/schema.sql` um Kategorie- und Bildfelder
|
- Legacy-Eigen-Events wurden erweitert in `src/App/AccountPages.php` und `Internal/db/schema.sql` um Kategorie- und Bildfelder
|
||||||
- Kategorien-Prüfung und Zusammenführung für Seiten-Admins liegen ebenfalls in `partials/landing/account/dashboard.php` mit Logik in `src/App/ListingCatalog.php`
|
- Kategorien-Prüfung und Zusammenführung für Seiten-Admins liegen ebenfalls in `partials/landing/account/dashboard.php` mit Logik in `src/App/ListingCatalog.php`
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale
|
|||||||
- Der Zwischenschritt vom eigenen Event zum Anlegen eines neuen Orts oder einer neuen Veranstaltung springt danach wieder in das Event zurück und wählt den neuen Eintrag direkt aus
|
- Der Zwischenschritt vom eigenen Event zum Anlegen eines neuen Orts oder einer neuen Veranstaltung springt danach wieder in das Event zurück und wählt den neuen Eintrag direkt aus
|
||||||
- Orte und sonstige Veranstaltungen wurden vorerst in einen separaten Bereich `Orte & Veranstaltungen` verschoben
|
- Orte und sonstige Veranstaltungen wurden vorerst in einen separaten Bereich `Orte & Veranstaltungen` verschoben
|
||||||
- Neue Orte und Veranstaltungen müssen vor Veröffentlichung erst durch einen Admin freigegeben werden; Änderungs- und Löschwünsche laufen ebenfalls nur als begründete Anfrage
|
- Neue Orte und Veranstaltungen müssen vor Veröffentlichung erst durch einen Admin freigegeben werden; Änderungs- und Löschwünsche laufen ebenfalls nur als begründete Anfrage
|
||||||
|
- Noch nicht veröffentlichte Orts- und Veranstaltungsvorschläge können im Mitgliederbereich direkt weiterbearbeitet werden
|
||||||
|
- `SiteOwner` übernimmt bei Orts- und Veranstaltungsanfragen vollständig die Freigaberechte von `Forum-Admin`
|
||||||
- Die Eingabemasken sind jetzt progressiv aufgebaut: erst Pflichtangaben, optionale Daten in einklappbaren Bereichen
|
- Die Eingabemasken sind jetzt progressiv aufgebaut: erst Pflichtangaben, optionale Daten in einklappbaren Bereichen
|
||||||
- Kategorien laufen jetzt über eine Sucheingabe mit bestehenden Vorschlägen; neue Kategorien werden automatisch angelegt und können im Systembereich von Seiten-Admins zusammengeführt werden
|
- Kategorien laufen jetzt über eine Sucheingabe mit bestehenden Vorschlägen; neue Kategorien werden automatisch angelegt und können im Systembereich von Seiten-Admins zusammengeführt werden
|
||||||
- Im Bereich `Events` gibt es jetzt zusätzlich einen ICS-Download und einen persönlichen abonnierbaren Kalender-Feed für alle eigenen Events und Event-Teilnahmen
|
- Im Bereich `Events` gibt es jetzt zusätzlich einen ICS-Download und einen persönlichen abonnierbaren Kalender-Feed für alle eigenen Events und Event-Teilnahmen
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events
|
|||||||
- Places and event-like entries were moved for now into a separate member-area section `Places & Events`.
|
- Places and event-like entries were moved for now into a separate member-area section `Places & Events`.
|
||||||
- Inside `Places & Events`, users can create permanent places and time-limited event-style entries.
|
- Inside `Places & Events`, users can create permanent places and time-limited event-style entries.
|
||||||
- New places and event-style entries stay in a pending state until an admin approves them for publication.
|
- New places and event-style entries stay in a pending state until an admin approves them for publication.
|
||||||
|
- Not-yet-published place and event-style suggestions can be edited directly by their creator inside the member area.
|
||||||
- Change and deletion wishes for published places and event-style entries always run through a reasoned moderation request.
|
- Change and deletion wishes for published places and event-style entries always run through a reasoned moderation request.
|
||||||
- Pending new places and event-style entries can already be used as location suggestions for events while they are still under review.
|
- Pending new places and event-style entries can already be used as location suggestions for events while they are still under review.
|
||||||
- Duplicate submissions for places and event-style entries should be blocked server-side at least by name and address.
|
- Duplicate submissions for places and event-style entries should be blocked server-side at least by name and address.
|
||||||
@@ -50,6 +51,7 @@ Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events
|
|||||||
- `Profile Levels` also includes a list of users who reached at least the rank `Pillar of the Fathers Community` within the last 30 days.
|
- `Profile Levels` also includes a list of users who reached at least the rank `Pillar of the Fathers Community` within the last 30 days.
|
||||||
- System levels remain separate as the roles `Forum Admin`, `Site Admin`, and `SiteOwner`.
|
- System levels remain separate as the roles `Forum Admin`, `Site Admin`, and `SiteOwner`.
|
||||||
- `Forum Admin` can already confirm and merge categories as well as approve places and event-style entries.
|
- `Forum Admin` can already confirm and merge categories as well as approve places and event-style entries.
|
||||||
|
- `SiteOwner` and `Site Admin` fully inherit those approval rights.
|
||||||
- System-level assignment in `Community Admin` now runs through user search instead of raw user IDs; site admins remain limited by the existing role rules.
|
- System-level assignment in `Community Admin` now runs through user search instead of raw user IDs; site admins remain limited by the existing role rules.
|
||||||
- Categories no longer live under `System`, but in their own member-area section `Categories`; that area only shows newly created categories and merges them into existing database categories through a suggestion field.
|
- Categories no longer live under `System`, but in their own member-area section `Categories`; that area only shows newly created categories and merges them into existing database categories through a suggestion field.
|
||||||
- New categories remain visible there until an authorized user confirms them or merges them into an existing category.
|
- New categories remain visible there until an authorized user confirms them or merges them into an existing category.
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ Updated: 2026-08-10
|
|||||||
- community-level rights for categories and place/event approvals: `config/community.php`, `src/App/Community.php`, `src/App/CommunityAccess.php`, `partials/landing/account/community-admin.php`
|
- community-level rights for categories and place/event approvals: `config/community.php`, `src/App/Community.php`, `src/App/CommunityAccess.php`, `partials/landing/account/community-admin.php`
|
||||||
- pricing, image upload, and place/address input for places and event-style entries plus a reduced own-event form: `partials/landing/account/dashboard.php` with persistence in `src/App/ListingCatalog.php`
|
- pricing, image upload, and place/address input for places and event-style entries plus a reduced own-event form: `partials/landing/account/dashboard.php` with persistence in `src/App/ListingCatalog.php`
|
||||||
- approvals as well as change and deletion requests for places and event-style entries: `src/App/ListingCatalog.php`, `partials/landing/account/dashboard.php`, `partials/landing/account/community-admin.php`
|
- approvals as well as change and deletion requests for places and event-style entries: `src/App/ListingCatalog.php`, `partials/landing/account/dashboard.php`, `partials/landing/account/community-admin.php`
|
||||||
|
- direct editing for not-yet-published place and event-style suggestions plus approval-right resolution: `src/App/CommunityAccess.php`, `src/App/AccountPages.php`, `src/App/ListingCatalog.php`, `partials/landing/account/dashboard.php`
|
||||||
- role assignment via user search in community admin: `partials/landing/account/community-admin.php`, `src/App/CommunityAccess.php`
|
- role assignment via user search in community admin: `partials/landing/account/community-admin.php`, `src/App/CommunityAccess.php`
|
||||||
- legacy own events were extended in `src/App/AccountPages.php` and `Internal/db/schema.sql` with category and image fields
|
- legacy own events were extended in `src/App/AccountPages.php` and `Internal/db/schema.sql` with category and image fields
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ Papa-Kind-Treff is a PHP-based platform for fathers focused on local events, app
|
|||||||
- when a user creates a new place or event-style listing from inside an own event, the flow returns to that event afterwards and preselects the newly created entry
|
- when a user creates a new place or event-style listing from inside an own event, the flow returns to that event afterwards and preselects the newly created entry
|
||||||
- places and other event-style entries were moved for now into a separate member-area section `Places & Events`
|
- places and other event-style entries were moved for now into a separate member-area section `Places & Events`
|
||||||
- new places and event-style entries must be approved by an admin before publication; change and deletion wishes also run as reasoned requests
|
- new places and event-style entries must be approved by an admin before publication; change and deletion wishes also run as reasoned requests
|
||||||
|
- not-yet-published place and event-style suggestions can be edited directly in the member area
|
||||||
|
- `SiteOwner` fully inherits the place and event approval rights from `Forum Admin`
|
||||||
- the member-area entry forms now follow a progressive approach: required fields first, optional data inside collapsible sections
|
- the member-area entry forms now follow a progressive approach: required fields first, optional data inside collapsible sections
|
||||||
- categories now use a search input with existing suggestions; new categories are created automatically and can be merged by site admins in the system area
|
- categories now use a search input with existing suggestions; new categories are created automatically and can be merged by site admins in the system area
|
||||||
- the `Events` area now also includes an ICS download and a personal subscribable calendar feed for all own events and event participations
|
- the `Events` area now also includes an ICS download and a personal subscribable calendar feed for all own events and event participations
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf:
|
|||||||
- Im Mitgliederbereich ist `Events` jetzt wieder auf echte eigene Events und Event-Teilnahmen beschränkt
|
- Im Mitgliederbereich ist `Events` jetzt wieder auf echte eigene Events und Event-Teilnahmen beschränkt
|
||||||
- Orte und sonstige Veranstaltungen laufen jetzt separat unter `Orte & Veranstaltungen`
|
- Orte und sonstige Veranstaltungen laufen jetzt separat unter `Orte & Veranstaltungen`
|
||||||
- Neue Orte und Veranstaltungen müssen vor Veröffentlichung erst durch einen Admin freigegeben werden; Änderungs- und Löschwünsche laufen ebenfalls als begründete Anfrage
|
- Neue Orte und Veranstaltungen müssen vor Veröffentlichung erst durch einen Admin freigegeben werden; Änderungs- und Löschwünsche laufen ebenfalls als begründete Anfrage
|
||||||
|
- Noch nicht veröffentlichte Orts- und Veranstaltungsvorschläge können im Mitgliederbereich direkt weiterbearbeitet werden; veröffentlichte Einträge laufen für normale Mitglieder weiter über begründete Änderungsanfragen
|
||||||
|
- `SiteOwner` erbt bei Orts- und Veranstaltungsanfragen vollständig die Freigaberechte von `Forum-Admin`
|
||||||
- Eigene Events unterstützen aktuell optionalen Beschreibungstext, klare Kinderangabe, optionale Platzzahl, Bild-Upload sowie eine Location aus Datenbank oder benutzerdefinierte Adresse
|
- Eigene Events unterstützen aktuell optionalen Beschreibungstext, klare Kinderangabe, optionale Platzzahl, Bild-Upload sowie eine Location aus Datenbank oder benutzerdefinierte Adresse
|
||||||
- Bei eigener Event-Location aus der Datenbank werden Adresse und Kategorie nur informativ aus dem gewählten Ort bzw. der gewählten Veranstaltung übernommen und nicht manuell geändert
|
- Bei eigener Event-Location aus der Datenbank werden Adresse und Kategorie nur informativ aus dem gewählten Ort bzw. der gewählten Veranstaltung übernommen und nicht manuell geändert
|
||||||
- Aus dem Formular für eigene Events kann direkt in das Anlegen eines neuen Orts oder einer neuen Veranstaltung verzweigt werden
|
- Aus dem Formular für eigene Events kann direkt in das Anlegen eines neuen Orts oder einer neuen Veranstaltung verzweigt werden
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ $restoreEventDraftActive = !empty($restoreEventDraftActive);
|
|||||||
$editingEvent = isset($editEvent) && $editEvent !== null;
|
$editingEvent = isset($editEvent) && $editEvent !== null;
|
||||||
$editingListing = isset($editListing) && $editListing !== null;
|
$editingListing = isset($editListing) && $editListing !== null;
|
||||||
$editing = $editingEvent || $editingListing;
|
$editing = $editingEvent || $editingListing;
|
||||||
|
$editingSuggestionDirectly = $editingListing && (string)($editListing['status'] ?? '') !== 'published';
|
||||||
$eventDraftValues = (!$editing && (($section ?? '') === 'events') && $restoreEventDraftActive && is_array($restoredEventDraft ?? null))
|
$eventDraftValues = (!$editing && (($section ?? '') === 'events') && $restoreEventDraftActive && is_array($restoredEventDraft ?? null))
|
||||||
? $restoredEventDraft
|
? $restoredEventDraft
|
||||||
: [];
|
: [];
|
||||||
@@ -31,8 +32,8 @@ if ($editingEvent && !empty($editEvent['starts_at'])) {
|
|||||||
$withChildrenValue = $editingEvent
|
$withChildrenValue = $editingEvent
|
||||||
? (((int)($editEvent['allow_kids'] ?? 1)) === 1 ? 'yes' : 'no')
|
? (((int)($editEvent['allow_kids'] ?? 1)) === 1 ? 'yes' : 'no')
|
||||||
: (!empty($eventDraftValues['with_children']) ? (string)$eventDraftValues['with_children'] : (($editingListing && $currentEntryKind === 'editorial_event' && !empty($editListing['supports_registration'])) ? 'yes' : 'yes'));
|
: (!empty($eventDraftValues['with_children']) ? (string)$eventDraftValues['with_children'] : (($editingListing && $currentEntryKind === 'editorial_event' && !empty($editListing['supports_registration'])) ? 'yes' : 'yes'));
|
||||||
$eventTitle = $editingEvent ? 'Event bearbeiten' : ($editingListing ? ($currentEntryKind === 'place' ? 'Änderung für Ort anfragen' : 'Änderung für Veranstaltung anfragen') : ((($section ?? 'events') === 'places') ? 'Ort oder Veranstaltung anlegen' : 'Neues Event anlegen'));
|
$eventTitle = $editingEvent ? 'Event bearbeiten' : ($editingListing ? ($editingSuggestionDirectly ? (($currentEntryKind === 'place') ? 'Ort bearbeiten' : 'Veranstaltung bearbeiten') : (($currentEntryKind === 'place') ? 'Änderung für Ort anfragen' : 'Änderung für Veranstaltung anfragen')) : ((($section ?? 'events') === 'places') ? 'Ort oder Veranstaltung anlegen' : 'Neues Event anlegen'));
|
||||||
$submitLabel = $editingEvent ? 'Event speichern' : ($editingListing ? 'Änderungsanfrage senden' : ((($section ?? 'events') === 'places') ? 'Eintrag zur Freigabe einreichen' : 'Event anlegen'));
|
$submitLabel = $editingEvent ? 'Event speichern' : ($editingListing ? ($editingSuggestionDirectly ? 'Änderungen speichern' : 'Änderungsanfrage senden') : ((($section ?? 'events') === 'places') ? 'Eintrag zur Freigabe einreichen' : 'Event anlegen'));
|
||||||
$titleValue = $editingEvent ? (string)($editEvent['title'] ?? '') : (!empty($eventDraftValues['title']) ? (string)$eventDraftValues['title'] : (string)($editListing['title'] ?? ''));
|
$titleValue = $editingEvent ? (string)($editEvent['title'] ?? '') : (!empty($eventDraftValues['title']) ? (string)$eventDraftValues['title'] : (string)($editListing['title'] ?? ''));
|
||||||
$teaserValue = $editingEvent ? (string)($editEvent['teaser_public'] ?? '') : (string)($editListing['teaser_public'] ?? '');
|
$teaserValue = $editingEvent ? (string)($editEvent['teaser_public'] ?? '') : (string)($editListing['teaser_public'] ?? '');
|
||||||
$descriptionValue = $editingEvent ? (string)($editEvent['description'] ?? '') : (!empty($eventDraftValues['description']) ? (string)$eventDraftValues['description'] : (string)($editListing['description'] ?? ''));
|
$descriptionValue = $editingEvent ? (string)($editEvent['description'] ?? '') : (!empty($eventDraftValues['description']) ? (string)$eventDraftValues['description'] : (string)($editListing['description'] ?? ''));
|
||||||
@@ -751,15 +752,25 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<ul class="dash-list" style="margin-top:12px;">
|
<ul class="dash-list" style="margin-top:12px;">
|
||||||
<?php foreach ($pendingListings as $entry): ?>
|
<?php foreach ($pendingListings as $entry): ?>
|
||||||
|
<?php $canEditPendingEntry = ((int)($entry['created_by'] ?? 0) === $dashboardUserId) || !empty($canReviewListings); ?>
|
||||||
<li>
|
<li>
|
||||||
<strong><?= htmlspecialchars((string)$entry['title'], ENT_QUOTES) ?></strong>
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:flex-start; flex-wrap:wrap;">
|
||||||
<span class="badge"><?= ($entry['listing_type'] ?? '') === 'place' ? 'Ort' : 'Veranstaltung' ?></span>
|
<div>
|
||||||
<span class="badge" style="background:#fff7e6; color:#8a5a00;">
|
<strong><?= htmlspecialchars((string)$entry['title'], ENT_QUOTES) ?></strong>
|
||||||
<?= (string)($entry['moderation_request_status'] ?? '') === 'rejected' ? 'Abgelehnt' : 'Wartet auf Freigabe' ?>
|
<span class="badge"><?= ($entry['listing_type'] ?? '') === 'place' ? 'Ort' : 'Veranstaltung' ?></span>
|
||||||
</span>
|
<span class="badge" style="background:#fff7e6; color:#8a5a00;">
|
||||||
<?php if (!empty($entry['moderation_review_note'])): ?>
|
<?= (string)($entry['moderation_request_status'] ?? '') === 'rejected' ? 'Abgelehnt' : 'Wartet auf Freigabe' ?>
|
||||||
<div class="muted small" style="margin-top:6px;">Admin-Hinweis: <?= htmlspecialchars((string)$entry['moderation_review_note'], ENT_QUOTES) ?></div>
|
</span>
|
||||||
<?php endif; ?>
|
<?php if (!empty($entry['moderation_review_note'])): ?>
|
||||||
|
<div class="muted small" style="margin-top:6px;">Admin-Hinweis: <?= htmlspecialchars((string)$entry['moderation_review_note'], ENT_QUOTES) ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php if ($canEditPendingEntry): ?>
|
||||||
|
<div class="flex gap-8" style="flex-wrap:wrap;">
|
||||||
|
<a class="btn ghost" href="/dashboard?section=places&edit_listing=<?= (int)$entry['id'] ?>#places">Bearbeiten</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -1593,12 +1604,14 @@ if (!empty($canManageSystemSettings)) {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if ($editingListing): ?>
|
<?php if ($editingListing && !$editingSuggestionDirectly): ?>
|
||||||
<div class="stack gap-6">
|
<div class="stack gap-6">
|
||||||
<label class="label" for="listingModerationReason">Begründung für die Änderungsanfrage</label>
|
<label class="label" for="listingModerationReason">Begründung für die Änderungsanfrage</label>
|
||||||
<textarea id="listingModerationReason" name="moderation_reason" class="textarea" rows="3" placeholder="Was stimmt nicht oder was soll angepasst werden?" required></textarea>
|
<textarea id="listingModerationReason" name="moderation_reason" class="textarea" rows="3" placeholder="Was stimmt nicht oder was soll angepasst werden?" required></textarea>
|
||||||
<p class="muted small" style="margin:0;">Die Änderung wird erst nach Prüfung durch einen Admin freigegeben.</p>
|
<p class="muted small" style="margin:0;">Die Änderung wird erst nach Prüfung durch einen Admin freigegeben.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<?php elseif ($editingSuggestionDirectly): ?>
|
||||||
|
<p class="muted small" style="margin:0;">Dieser Vorschlag ist noch nicht veröffentlicht und kann direkt aktualisiert werden.</p>
|
||||||
<?php elseif (($section ?? '') === 'places'): ?>
|
<?php elseif (($section ?? '') === 'places'): ?>
|
||||||
<p class="muted small" style="margin:0;">Neue Orte und Veranstaltungen werden erst nach Prüfung durch einen Admin freigegeben.</p>
|
<p class="muted small" style="margin:0;">Neue Orte und Veranstaltungen werden erst nach Prüfung durch einen Admin freigegeben.</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ final class AccountPages
|
|||||||
$canManageProfileLevels = $communityAccess ? $communityAccess->canManageRoles($userId) : false;
|
$canManageProfileLevels = $communityAccess ? $communityAccess->canManageRoles($userId) : false;
|
||||||
$communityPointsForAccess = $community ? $community->computePoints($userId) : 0.0;
|
$communityPointsForAccess = $community ? $community->computePoints($userId) : 0.0;
|
||||||
$canManageCategories = $communityAccess ? $communityAccess->canManageCategories($userId, $communityPointsForAccess) : false;
|
$canManageCategories = $communityAccess ? $communityAccess->canManageCategories($userId, $communityPointsForAccess) : false;
|
||||||
|
$canReviewListings = $communityAccess ? $communityAccess->canReviewListings($userId, $communityPointsForAccess) : false;
|
||||||
$allowedSections = ['profile', 'children', 'events', 'places', 'community', 'settings'];
|
$allowedSections = ['profile', 'children', 'events', 'places', 'community', 'settings'];
|
||||||
if ($canManageSystemSettings) {
|
if ($canManageSystemSettings) {
|
||||||
$allowedSections[] = 'system';
|
$allowedSections[] = 'system';
|
||||||
@@ -471,14 +472,28 @@ final class AccountPages
|
|||||||
trim((string)($payload['description'] ?? '')),
|
trim((string)($payload['description'] ?? '')),
|
||||||
trim((string)($payload['title'] ?? ''))
|
trim((string)($payload['title'] ?? ''))
|
||||||
);
|
);
|
||||||
if ($action === 'event_update') {
|
$canDirectListingEdit = is_array($existingListing)
|
||||||
$listingCatalog->submitUpdateRequest(
|
&& (string)($existingListing['status'] ?? '') !== 'published'
|
||||||
$userId,
|
&& (
|
||||||
(int)($_POST['listing_id'] ?? 0),
|
(int)($existingListing['created_by'] ?? 0) === $userId
|
||||||
$payload,
|
|| $canReviewListings
|
||||||
(string)($_POST['moderation_reason'] ?? '')
|
|
||||||
);
|
);
|
||||||
$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 {
|
} else {
|
||||||
$createdListingId = $listingCatalog->submitCreateSuggestion($userId, $payload);
|
$createdListingId = $listingCatalog->submitCreateSuggestion($userId, $payload);
|
||||||
$info = $entryKind === 'place' ? 'Ort zur Freigabe eingereicht.' : 'Veranstaltung zur Freigabe eingereicht.';
|
$info = $entryKind === 'place' ? 'Ort zur Freigabe eingereicht.' : 'Veranstaltung zur Freigabe eingereicht.';
|
||||||
@@ -957,7 +972,13 @@ final class AccountPages
|
|||||||
$editListingId = (int)$_GET['edit_listing'];
|
$editListingId = (int)$_GET['edit_listing'];
|
||||||
if ($editListingId > 0) {
|
if ($editListingId > 0) {
|
||||||
$candidate = $listingCatalog->getMemberEntry($editListingId);
|
$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;
|
$editListing = $candidate;
|
||||||
} else {
|
} else {
|
||||||
$error = 'Der gewünschte Eintrag ist für eine Änderungsanfrage nicht verfügbar.';
|
$error = 'Der gewünschte Eintrag ist für eine Änderungsanfrage nicht verfügbar.';
|
||||||
@@ -1082,6 +1103,7 @@ final class AccountPages
|
|||||||
'communityLevelDefinitions',
|
'communityLevelDefinitions',
|
||||||
'communityLevelRightDefinitions',
|
'communityLevelRightDefinitions',
|
||||||
'communityRoles',
|
'communityRoles',
|
||||||
|
'canReviewListings',
|
||||||
'systemRoleAssignments',
|
'systemRoleAssignments',
|
||||||
'recentHighLevelUsers',
|
'recentHighLevelUsers',
|
||||||
'recentHighLevelThresholdLabel',
|
'recentHighLevelThresholdLabel',
|
||||||
|
|||||||
@@ -86,10 +86,7 @@ final class CommunityAccess
|
|||||||
|
|
||||||
public function canReviewListings(int $userId, ?float $points = null): bool
|
public function canReviewListings(int $userId, ?float $points = null): bool
|
||||||
{
|
{
|
||||||
if ($this->hasRole($userId, 'owner')) {
|
if ($this->hasRole($userId, 'owner') || $this->hasRole($userId, 'site_admin') || $this->hasRole($userId, 'forum_admin')) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($this->hasRole($userId, 'site_admin') || $this->hasRole($userId, 'forum_admin')) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -649,7 +649,7 @@ final class ListingCatalog
|
|||||||
{
|
{
|
||||||
$this->ensureSchema();
|
$this->ensureSchema();
|
||||||
$stmt = $this->pdo->prepare(
|
$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.id AS occurrence_id, lo.starts_at, lo.ends_at, lo.occurrence_type,
|
||||||
lo.recurrence_rule, lo.recurrence_until, lo.capacity_total,
|
lo.recurrence_rule, lo.recurrence_until, lo.capacity_total,
|
||||||
lc.slug AS category_slug
|
lc.slug AS category_slug
|
||||||
@@ -850,6 +850,27 @@ final class ListingCatalog
|
|||||||
return $this->createModerationRequest($listingId, 'delete', $userId, $reason, null);
|
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
|
public function listOpenModerationRequests(): array
|
||||||
{
|
{
|
||||||
$this->ensureSchema();
|
$this->ensureSchema();
|
||||||
|
|||||||
Reference in New Issue
Block a user