This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user