From 43fcc6cb9578168a5436d0151c132c06cf3fee6d Mon Sep 17 00:00:00 2001 From: M_Viper Date: Sun, 29 Mar 2026 13:41:29 +0200 Subject: [PATCH] Update from Git Manager GUI --- admin/forum-admin.php | 375 +++++++++++++++++++++++++++++---------- admin/forum-settings.php | 7 + 2 files changed, 289 insertions(+), 93 deletions(-) diff --git a/admin/forum-admin.php b/admin/forum-admin.php index a277909..d5f2701 100644 --- a/admin/forum-admin.php +++ b/admin/forum-admin.php @@ -553,7 +553,6 @@ function wbf_admin_page() { ['wbf-trash', 'fas fa-trash-can', 'Papierkorb', $deleted_count>0?$deleted_count:0, true], ['wbf-export', 'fas fa-database', 'Export / Import'], ['wbf-settings', 'fas fa-gear', 'Einstellungen'], - ['wbf-updates', 'fas fa-arrow-up-from-bracket', '🔔 Updates', $update_info ? 1 : 0], ]; foreach ($nav as $n): if ($n===null) { echo '
'; continue; } @@ -1079,6 +1078,10 @@ function wbf_admin_categories() { foreach ( $p->children as $c ) { $cd = wp_nonce_url( "?page=wbf-categories&delete_cat={$c->id}", "delete_cat_{$c->id}" ); $crole = WBF_Roles::get( $c->min_role ?? 'member' ); + $clbadge = ( $c->min_role ?? 'member' ) !== 'member' + ? " 🔒 " . esc_html( $crole['label'] ) . "" : ''; + $cguestbadge = ( (int)($c->guest_visible ?? 1) === 0 ) + ? " 👁 Nur eingeloggt" : ''; $reorder_c = '
' . wp_nonce_field( 'wbf_reorder_nonce', '_wpnonce', true, false ) @@ -1097,7 +1100,7 @@ function wbf_admin_categories() { echo " ↳ " . esc_html( $c->name ) . " " . esc_html( $c->thread_count ) . " - " . esc_html( $crole['label'] ) . "$clockbadge$cguestbadge + " . esc_html( $crole['label'] ) . "$clbadge$cguestbadge {$reorder_c} Bearbeiten | Löschen "; } @@ -1428,6 +1431,7 @@ function wbf_admin_members() { display_name ); ?>
@username ); ?> + email ); ?> @@ -3039,151 +3043,328 @@ function wbf_admin_export() { function wbf_admin_profile_fields() { - // ── Speichern ──────────────────────────────────────────────────────────── + // ── Kategorien speichern ───────────────────────────────────────────────── if ( isset($_POST['wbf_save_profile_fields']) && check_admin_referer('wbf_profile_fields_nonce') ) { - $keys = $_POST['field_key'] ?? []; - $labels = $_POST['field_label'] ?? []; - $types = $_POST['field_type'] ?? []; - $placeholders = $_POST['field_placeholder'] ?? []; - $required = $_POST['field_required'] ?? []; - $public = $_POST['field_public'] ?? []; - $options = $_POST['field_options'] ?? []; + // Kategorien + $cat_ids = $_POST['cat_id'] ?? []; + $cat_names = $_POST['cat_name'] ?? []; + $cat_icons = $_POST['cat_icon'] ?? []; + $cats = []; + foreach ( $cat_ids as $ci => $cid ) { + $cid = sanitize_key( $cid ); + if ( ! $cid ) continue; + $cats[] = [ + 'id' => $cid, + 'name' => sanitize_text_field( $cat_names[$ci] ?? $cid ), + 'icon' => sanitize_text_field( $cat_icons[$ci] ?? '📋' ), + ]; + } + // Neue Kategorie + if ( ! empty( trim( $_POST['new_cat_name'] ?? '' ) ) ) { + $new_name = sanitize_text_field( $_POST['new_cat_name'] ); + $new_icon = sanitize_text_field( $_POST['new_cat_icon'] ?? '📋' ); + $new_id = 'cat_' . sanitize_key( $new_name ) . '_' . time(); + $cats[] = [ 'id' => $new_id, 'name' => $new_name, 'icon' => $new_icon ]; + } + WBF_DB::save_profile_field_categories( $cats ); + + // Felder + $keys = $_POST['field_key'] ?? []; + $labels = $_POST['field_label'] ?? []; + $types = $_POST['field_type'] ?? []; + $phs = $_POST['field_placeholder'] ?? []; + $req = $_POST['field_required'] ?? []; + $pub = $_POST['field_public'] ?? []; + $opts = $_POST['field_options'] ?? []; + $cats_f = $_POST['field_category'] ?? []; + + $valid_cat_ids = array_column( $cats, 'id' ); $fields = []; foreach ( $keys as $i => $raw_key ) { $key = sanitize_key( $raw_key ); if ( ! $key ) continue; - // Reservierte Keys sperren if ( in_array($key, ['username','email','password','display_name','bio','signature','avatar_url','role']) ) continue; + $cat_id = sanitize_key( $cats_f[$i] ?? '' ); + if ( ! in_array( $cat_id, $valid_cat_ids ) ) $cat_id = ''; $fields[] = [ 'key' => $key, 'label' => sanitize_text_field( $labels[$i] ?? $key ), - 'type' => in_array($types[$i] ?? '', ['text','url','textarea','select','number']) ? $types[$i] : 'text', - 'placeholder' => sanitize_text_field( $placeholders[$i] ?? '' ), - 'required' => ! empty( $required[$i] ) ? 1 : 0, - 'public' => ! empty( $public[$i] ) ? 1 : 0, - 'options' => sanitize_textarea_field( $options[$i] ?? '' ), + 'type' => in_array($types[$i] ?? '', ['text','url','textarea','select','number','date']) ? $types[$i] : 'text', + 'placeholder' => sanitize_text_field( $phs[$i] ?? '' ), + 'required' => ! empty( $req[$i] ) ? 1 : 0, + 'public' => ! empty( $pub[$i] ) ? 1 : 0, + 'options' => sanitize_textarea_field( $opts[$i] ?? '' ), + 'category_id' => $cat_id, ]; } WBF_DB::save_profile_field_defs( $fields ); - echo '

✅ Profilfelder gespeichert!

'; + echo '

✅ Profilfelder & Kategorien gespeichert!

'; } - $fields = WBF_DB::get_profile_field_defs(); - $types = ['text'=>'Text','url'=>'URL/Link','textarea'=>'Mehrzeiliger Text','select'=>'Auswahlliste','number'=>'Zahl']; + // Kategorie löschen + if ( isset($_GET['wbf_del_cat']) && check_admin_referer('wbf_del_cat') ) { + $del_id = sanitize_key( $_GET['wbf_del_cat'] ); + $cats = WBF_DB::get_profile_field_categories(); + $cats = array_values( array_filter( $cats, fn($c) => $c['id'] !== $del_id ) ); + WBF_DB::save_profile_field_categories( $cats ); + // Felder dieser Kategorie auf "keine Kategorie" setzen + $fields = WBF_DB::get_profile_field_defs(); + foreach ( $fields as &$f ) { + if ( ($f['category_id'] ?? '') === $del_id ) $f['category_id'] = ''; + } + WBF_DB::save_profile_field_defs( $fields ); + wp_safe_redirect( remove_query_arg(['wbf_del_cat','_wpnonce']) ); + exit; + } + + $fields = WBF_DB::get_profile_field_defs(); + $cats = WBF_DB::get_profile_field_categories(); + $cat_map = array_column( $cats, null, 'id' ); + $type_opts = ['text'=>'Text','url'=>'URL/Link','textarea'=>'Mehrzeiliger Text','select'=>'Auswahlliste','number'=>'Zahl','date'=>'Datum (Alter)']; + + // Felder nach Kategorie gruppieren + $by_cat = []; + foreach ( $fields as $f ) { + $cid = $f['category_id'] ?? ''; + if ( ! $cid || ! isset($cat_map[$cid]) ) $cid = '__none__'; + $by_cat[$cid][] = $f; + } ?>
-

👤 Benutzerdefinierte Profilfelder

-

Felder die Nutzer in ihrem Profil ausfüllen können — z.B. Website, Ort, Discord-Name, etc.

+

👤 Benutzerdefinierte Profilfelder

+

Felder die Nutzer in ihrem Profil ausfüllen können — z.B. Website, Ort, Discord-Name, etc.

- - + + - + +
+

+ 🗂️ Kategorien verwalten +

+
- - - - - - - - + + + - + + $cat ): ?> + + + + + + + + + + + +
SchlüsselBezeichnungTypPlatzhalterOptionen (bei Auswahl)PflichtÖffentlich
IconKategorie-Name
+ + + + + + 'wbf-profile-fields','wbf_del_cat'=>$cat['id']], admin_url('admin.php')), + 'wbf_del_cat' + ); ?> + × +
+ + + +
+
+ + + '__none__','name'=>'Ohne Kategorie','icon'=>'📋']; + } + foreach ( $all_sections as $cat ): + $cid = $cat['id']; + $c_fields = $by_cat[$cid] ?? []; + ?> +
+
+ + + Feld +
+
+ + + + + + + + + + + + + + + '','label'=>'','type'=>'text','placeholder'=>'','required'=>0,'public'=>1,'options'=>'']; - foreach ( $rows as $i => $f ): + if ( empty($c_fields) ): + ?> + + + + $f ): + $fi = 'fi_' . $f['key']; ?> - - - + - - + - - - +
SchlüsselBezeichnungTypPlatzhalterOptionenPflichtÖffentlichKategorie
+ Noch keine Felder in dieser Kategorie. +
+ > -

Schlüssel kann nach Erstellung nicht geändert werden.

+

Nicht änderbar

+ + + + + + - > + + > - > + + > - + + + +
- -
- - +
+
- +
+
+ -
-

ℹ️ Hinweise

-
    -
  • Schlüssel: Einmalig, nur Kleinbuchstaben/Zahlen/Unterstrich. Kann nach dem ersten Speichern nicht mehr geändert werden.
  • -
  • Typ URL: Wird automatisch als klickbarer Link dargestellt.
  • -
  • Typ Auswahlliste: Trage die Optionen zeilenweise ins Optionen-Feld ein.
  • -
  • Öffentlich: Wenn deaktiviert, sieht nur der Nutzer selbst das Feld in seinem Profil.
  • -
  • Pflicht: Verhindert das Speichern wenn das Feld leer ist.
  • -
+
+ +
+ + +
+

ℹ️ Hinweise

+
    +
  • Schlüssel: Einmalig, nur Kleinbuchstaben/Zahlen/Unterstrich. Kann nach dem ersten Speichern nicht mehr geändert werden.
  • +
  • Typ URL: Wird automatisch als klickbarer Link dargestellt.
  • +
  • Typ Datum (Alter): Speichert das Geburtsdatum und zeigt nur das Alter an.
  • +
  • Typ Auswahlliste: Trage die Optionen zeilenweise ins Optionen-Feld ein.
  • +
  • Öffentlich: Wenn deaktiviert, sieht nur der Nutzer selbst das Feld in seinem Profil.
  • +
  • Pflicht: Verhindert das Speichern wenn das Feld leer ist.
  • +
  • Kategorie: Felder werden im Profil nach Kategorie gruppiert dargestellt.
  • +