sadasd
All checks were successful
Deploy / deploy (push) Successful in 56s

This commit is contained in:
2026-08-19 20:04:01 +02:00
parent c2eaa5c186
commit c567d19deb
13 changed files with 177 additions and 38 deletions

View File

@@ -180,9 +180,13 @@ final class AccountPages
$section = (string)($_GET['section'] ?? 'profile');
$canManageSystemSettings = $communityAccess ? $communityAccess->canManageApplications($userId) : false;
$canManageProfileLevels = $communityAccess ? $communityAccess->canManageRoles($userId) : false;
$communityPointsForAccess = $community ? $community->computePoints($userId) : 0.0;
$canManageCategories = $communityAccess ? $communityAccess->canManageCategories($userId, $communityPointsForAccess) : false;
$allowedSections = ['profile', 'children', 'events', 'places', 'community', 'settings'];
if ($canManageSystemSettings) {
$allowedSections[] = 'system';
}
if ($canManageCategories) {
$allowedSections[] = 'categories';
}
if ($canManageProfileLevels) {
@@ -326,7 +330,7 @@ final class AccountPages
], $userId);
$info = 'System-Einstellungen gespeichert.';
} elseif ($action === 'category_merge') {
if (!$canManageSystemSettings || !$listingCatalog) {
if (!$canManageCategories || !$listingCatalog) {
throw new \RuntimeException('Keine Berechtigung für die Kategorien-Verwaltung.');
}
$targetCategorySlug = $listingCatalog->resolveExistingCategorySlug((string)($_POST['target_category_input'] ?? ''));
@@ -338,6 +342,12 @@ final class AccountPages
$targetCategorySlug
);
$info = 'Kategorie zusammengeführt.';
} elseif ($action === 'category_confirm') {
if (!$canManageCategories || !$listingCatalog) {
throw new \RuntimeException('Keine Berechtigung für die Kategorien-Verwaltung.');
}
$listingCatalog->confirmCategory((string)($_POST['source_category_slug'] ?? ''));
$info = 'Kategorie bestätigt.';
} elseif ($action === 'child_add' || $action === 'child_update') {
$crypto = self::requireCrypto($crypto, 'Kinder');
$childId = (int)($_POST['child_id'] ?? 0);
@@ -857,7 +867,7 @@ final class AccountPages
$restoreEventDraftActive = $section === 'events' && ((string)($_GET['restore_event_draft'] ?? '')) === '1' && self::hasStoredEventDraft();
$restoredEventDraft = $restoreEventDraftActive ? self::getStoredEventDraft() : null;
$listingCategories = $listingCatalog ? $listingCatalog->listCategories(['general', 'place', 'food', 'event', 'family']) : [];
$categoryReviewItems = $listingCatalog && $canManageSystemSettings ? array_values(array_filter(
$categoryReviewItems = $listingCatalog && $canManageCategories ? array_values(array_filter(
$listingCatalog->listCategoryReviewItems(),
static fn(array $item): bool => !empty($item['needs_review'])
)) : [];
@@ -940,7 +950,7 @@ final class AccountPages
}
}
$communityPoints = $community ? $community->computePoints($userId) : 0.0;
$communityPoints = $communityPointsForAccess;
$communityLevel = $community ? $community->membershipLevel($communityPoints) : ['label' => '', 'icon' => ''];
$communityLevelDefinitions = $community ? $community->listMembershipLevels() : [];
$communityLevelRightDefinitions = Community::membershipRightDefinitions();
@@ -990,6 +1000,7 @@ final class AccountPages
'Themen und Antworten moderieren',
'Community-Sperren setzen und aufheben',
'Meldungen bearbeiten',
'Orte und Veranstaltungen freigeben',
],
],
[
@@ -998,6 +1009,7 @@ final class AccountPages
'rights' => [
'Beinhaltet alle Rechte von Forum-Admin',
'Community-Admin-Bewerbungen bearbeiten',
'Kategorien bestätigen und zusammenführen',
'System-Einstellungen verwalten',
],
],
@@ -1061,6 +1073,7 @@ final class AccountPages
'communityCanApply',
'communityRestrictions',
'systemLevelDefinitions',
'canManageCategories',
'canManageSystemSettings',
'canManageProfileLevels',
'systemSettingsValues',

View File

@@ -657,6 +657,12 @@ final class Community
'can_apply_for_forum_admin' => [
'label' => 'Bewerbung als Forum-Admin',
],
'can_manage_categories' => [
'label' => 'Kategorien bestätigen und zusammenführen',
],
'can_review_listings' => [
'label' => 'Orte und Veranstaltungen freigeben',
],
];
}

View File

@@ -75,6 +75,35 @@ final class CommunityAccess
return $this->hasRole($userId, 'owner');
}
public function canManageCategories(int $userId, ?float $points = null): bool
{
if ($this->hasRole($userId, 'owner') || $this->hasRole($userId, 'site_admin')) {
return true;
}
return $this->resolveLevelRight($points ?? $this->resolveUserPoints($userId), 'can_manage_categories');
}
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')) {
return true;
}
return $this->resolveLevelRight($points ?? $this->resolveUserPoints($userId), 'can_review_listings');
}
public function canAccessCommunityAdmin(int $userId, ?float $points = null): bool
{
return $this->canModerateForum($userId)
|| $this->canManageApplications($userId)
|| $this->canManageRoles($userId)
|| $this->canReviewListings($userId, $points);
}
public function getRestrictionState(int $userId): array
{
$state = [
@@ -574,4 +603,14 @@ final class CommunityAccess
$level = $community->membershipLevelMeta($points);
return !empty($level['rights'][$rightKey]);
}
private function resolveUserPoints(int $userId): float
{
if ($userId <= 0) {
return 0.0;
}
$community = new Community($this->pdo, $this->communityConfig);
return $community->computePoints($userId);
}
}

View File

@@ -368,6 +368,35 @@ final class ListingCatalog
}
}
public function confirmCategory(string $sourceSlug): void
{
$this->ensureSchema();
$sourceSlug = trim($sourceSlug);
if ($sourceSlug === '') {
throw new \RuntimeException('Kategorie nicht gefunden.');
}
$lookup = $this->pdo->prepare('SELECT id, sort_order FROM listing_categories WHERE slug = :slug LIMIT 1');
$lookup->execute(['slug' => $sourceSlug]);
$source = $lookup->fetch(\PDO::FETCH_ASSOC);
if (!$source) {
throw new \RuntimeException('Kategorie nicht gefunden.');
}
if ((int)($source['sort_order'] ?? 0) < 900) {
return;
}
$maxStmt = $this->pdo->query('SELECT COALESCE(MAX(sort_order), 0) FROM listing_categories WHERE sort_order < 900');
$maxSortOrder = (int)($maxStmt?->fetchColumn() ?: 0);
$newSortOrder = max(1, $maxSortOrder + 1);
$update = $this->pdo->prepare('UPDATE listing_categories SET sort_order = :sortOrder, updated_at = NOW() WHERE id = :id');
$update->execute([
'sortOrder' => $newSortOrder,
'id' => (int)$source['id'],
]);
}
public function resolveExistingCategorySlug(string $input): ?string
{
$this->ensureSchema();