' . (int) $count . ''; break; } } }, 999 ); // ── Export via admin_init (läuft vor WordPress-Output/Headern) ──────────────── add_action( 'admin_init', function() { if ( ! isset( $_POST['wbf_do_export'] ) ) return; if ( ! check_admin_referer( 'wbf_export_nonce' ) ) return; if ( ! current_user_can( 'manage_options' ) ) return; $sections = array_keys( array_filter( $_POST['export_sections'] ?? [] ) ); $data = [ '_meta' => [ 'plugin' => 'WP Business Forum', 'version' => WBF_VERSION, 'exported' => date('c'), 'site' => get_bloginfo('url'), 'sections' => $sections, ], ]; global $wpdb; foreach ( $sections as $sec ) { switch ( $sec ) { case 'settings': $data['settings'] = get_option('wbf_settings', []); break; case 'roles': $data['roles'] = get_option('wbf_custom_roles', []); break; case 'levels': $data['levels'] = [ 'config' => get_option('wbf_level_config', []), 'enabled' => get_option('wbf_levels_enabled', true), ]; break; case 'categories': $data['categories'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_categories ORDER BY parent_id ASC, sort_order ASC", ARRAY_A ); break; case 'users': $data['users'] = $wpdb->get_results( "SELECT id, username, email, password, display_name, avatar_url, bio, signature, role, post_count, registered, last_active, ban_reason FROM {$wpdb->prefix}forum_users ORDER BY id ASC", ARRAY_A ); break; case 'threads': $data['threads'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_threads ORDER BY id ASC", ARRAY_A ); $data['posts'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_posts ORDER BY id ASC", ARRAY_A ); $data['thread_tags'] = $wpdb->get_results( "SELECT tt.*, t.name, t.slug, t.use_count FROM {$wpdb->prefix}forum_thread_tags tt JOIN {$wpdb->prefix}forum_tags t ON t.id = tt.tag_id ORDER BY tt.thread_id ASC", ARRAY_A ); break; case 'interactions': $data['likes'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_likes ORDER BY id ASC", ARRAY_A ); $data['reactions'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_reactions ORDER BY id ASC", ARRAY_A ); $data['notifications'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_notifications ORDER BY id ASC", ARRAY_A ); break; case 'messages': $data['messages'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_messages ORDER BY id ASC", ARRAY_A ); break; case 'reports': $data['reports'] = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}forum_reports ORDER BY id ASC", ARRAY_A ); break; } } $json = wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); $filename = 'wbf-backup-' . date('Y-m-d-His') . '.json'; header( 'Content-Type: application/json; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Length: ' . strlen( $json ) ); header( 'Cache-Control: no-cache, no-store, must-revalidate' ); echo $json; exit; } ); // ── Inline Styles ───────────────────────────────────────────────────────────── add_action( 'admin_head', function() { if ( ! isset( $_GET['page'] ) || strpos( $_GET['page'], 'wbf-' ) === false ) return; echo ''; } ); // ── Dashboard ───────────────────────────────────────────────────────────────── function wbf_admin_page() { $stats = WBF_DB::get_stats(); $roles = WBF_Roles::get_sorted(); $open_reports = WBF_DB::count_open_reports(); $recent = WBF_DB::get_recent_threads(6); $members = WBF_DB::get_all_users(5); $newest = $stats['newest'] ?? '—'; $admin_url = admin_url('admin.php'); ?>

Business Forum — Dashboard

Forum-Shortcode Füge [business_forum] auf einer Seite ein, um das Forum anzuzeigen.
'fas fa-comments', 'color'=>'#eff6ff','icolor'=>'#3b82f6', 'val'=>$stats['threads'], 'label'=>'Threads'], ['icon'=>'fas fa-comment-dots','color'=>'#f0fdf4','icolor'=>'#22c55e', 'val'=>$stats['posts'], 'label'=>'Beiträge'], ['icon'=>'fas fa-users', 'color'=>'#fdf4ff','icolor'=>'#a855f7', 'val'=>$stats['members'], 'label'=>'Mitglieder'], ['icon'=>'fas fa-flag', 'color'=>'#fff7ed','icolor'=>'#f97316', 'val'=>$open_reports, 'label'=>'Meldungen offen'], ['icon'=>'fas fa-tags', 'color'=>'#f0fdfa','icolor'=>'#14b8a6', 'val'=>0, 'label'=>'Tags gesamt'], ]; // Get tag count global $wpdb; $stat_items[4]['val'] = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}forum_tags"); foreach ( $stat_items as $si ): $link = ''; if ($si['label']==='Offene Meldungen') $link = esc_url(add_query_arg(['page'=>'wbf-reports'], $admin_url)); if ($si['label']==='Mitglieder') $link = esc_url(add_query_arg(['page'=>'wbf-members'], $admin_url)); ?>
Aktive Rollen
$role ): $color = esc_attr($role['color']); $bg = esc_attr($role['bg_color']); ?> Lvl

Superadmin ist automatisch an den WordPress-Administrator gebunden.

Schnellzugriff
Letzte Threads

Noch keine Threads vorhanden.

Neueste Mitglieder

Noch keine Mitglieder.

    role); $col = esc_attr($role['color']); $bg = esc_attr($role['bg_color']); ?>
  • post_count; ?> Beitr.
$label ) { if ( ! empty( $_POST['perm_' . $p] ) ) $perms[] = $p; } WBF_Roles::save( $key, [ 'label' => sanitize_text_field( $_POST['role_label'] ), 'level' => max( -1, min( 99, (int) $_POST['role_level'] ) ), 'color' => sanitize_hex_color( $_POST['role_color'] ) ?: '#94a3b8', 'bg_color' => sanitize_text_field( $_POST['role_bg'] ) ?: 'rgba(148,163,184,.1)', 'icon' => sanitize_text_field( $_POST['role_icon'] ) ?: 'fas fa-user', 'permissions' => $perms, 'locked' => false, 'description' => sanitize_textarea_field( $_POST['role_desc'] ), ] ); echo '

Rolle gespeichert!

'; } } if ( isset( $_POST['wbf_create_role'] ) && check_admin_referer( 'wbf_role_create_nonce' ) ) { $new_key = sanitize_key( $_POST['new_role_key'] ?? '' ); if ( $new_key && $new_key !== WBF_Roles::SUPERADMIN ) { $perms = []; foreach ( $all_perms as $p => $label ) { if ( ! empty( $_POST['new_perm_' . $p] ) ) $perms[] = $p; } WBF_Roles::save( $new_key, [ 'label' => sanitize_text_field( $_POST['new_role_label'] ?: ucfirst( $new_key ) ), 'level' => max( 1, min( 79, (int) ( $_POST['new_role_level'] ?? 10 ) ) ), 'color' => sanitize_hex_color( $_POST['new_role_color'] ) ?: '#94a3b8', 'bg_color' => 'rgba(148,163,184,.1)', 'icon' => sanitize_text_field( $_POST['new_role_icon'] ) ?: 'fas fa-user', 'permissions' => $perms, 'locked' => false, 'description' => sanitize_textarea_field( $_POST['new_role_desc'] ), ] ); echo '

Neue Rolle erstellt!

'; } } if ( isset( $_GET['delete_role'] ) && check_admin_referer( 'delete_role_' . $_GET['delete_role'] ) ) { $del = sanitize_key( $_GET['delete_role'] ); if ( WBF_Roles::delete( $del ) ) { echo '

Rolle gelöscht. Nutzer auf "member" gesetzt.

'; } else { echo '

Diese Rolle kann nicht gelöscht werden.

'; } } $roles = WBF_Roles::get_sorted(); $edit_key = isset( $_GET['edit_role'] ) ? sanitize_key( $_GET['edit_role'] ) : null; $edit_role = $edit_key ? WBF_Roles::get( $edit_key ) : null; echo '

Rollen-Verwaltung + Neue Rolle

'; echo ''; foreach ( $roles as $key => $role ) { $color = esc_attr( $role['color'] ); $bg = esc_attr( $role['bg_color'] ); $badge = " " . esc_html( $role['label'] ) . ""; $perms = implode( ', ', array_map( fn($p) => esc_html( $all_perms[$p] ?? $p ), $role['permissions'] ?? [] ) ); if ( in_array( 'all', $role['permissions'] ?? [] ) ) $perms = 'Alle Rechte'; $actions = ''; if ( $key !== WBF_Roles::SUPERADMIN ) { $actions .= "Bearbeiten"; if ( ! in_array( $key, ['member'] ) ) { $del_url = wp_nonce_url( "?page=wbf-roles&delete_role={$key}", "delete_role_{$key}" ); $actions .= " | Löschen"; } } else { $actions = 'Systemrolle — unveränderlich'; } echo ""; } echo '
RolleLevelPermissionsBeschreibungAktionen
$badge " . ( ( $role['locked'] ?? false ) ? '(🔒)' : '' ) . " " . esc_html( $role['level'] ) . " $perms " . esc_html( $role['description'] ?? '' ) . " $actions
'; if ( $edit_role && $edit_key !== WBF_Roles::SUPERADMIN ) { echo '

Bearbeiten: ' . esc_html( $edit_role['label'] ) . '

'; echo '
'; wp_nonce_field( 'wbf_role_edit_nonce' ); echo ''; wbf_role_form_fields( $edit_role, $all_perms, '' ); echo '
'; submit_button( 'Änderungen speichern', 'primary', 'wbf_save_role' ); echo '

'; } echo '

Neue Rolle erstellen

'; wp_nonce_field( 'wbf_role_create_nonce' ); echo ''; wbf_role_form_fields( null, $all_perms, 'new_' ); echo '
Rollen-Schlüssel *

Nur Kleinbuchstaben, Zahlen, Unterstriche. Unveränderlich.

'; submit_button( 'Rolle erstellen', 'primary', 'wbf_create_role' ); echo '
'; } function wbf_role_form_fields( $role, $all_perms, $prefix ) { $v = fn($k, $d = '') => esc_attr( $role[$k] ?? $d ); $perms = $role['permissions'] ?? []; echo " Anzeigename * Level

Superadmin=100, Admin≤80, Mod≤50, Member=10, Banned=-1

Farbe Icon

FontAwesome 6, z.B. fas fa-crown

Beschreibung Permissions
"; foreach ( $all_perms as $p => $label ) { $checked = in_array( $p, $perms ) ? 'checked' : ''; echo ""; } echo "
"; } // ── Kategorien ──────────────────────────────────────────────────────────────── function wbf_admin_categories() { global $wpdb; $roles = WBF_Roles::get_sorted(); // ── Reihenfolge verschieben ────────────────────────────────────────────── if ( isset( $_POST['wbf_reorder_cat'] ) && check_admin_referer( 'wbf_reorder_nonce' ) ) { $move_id = (int) $_POST['cat_id']; $dir = ( $_POST['direction'] ?? '' ) === 'up' ? 'up' : 'down'; $parent = (int) $_POST['parent_id']; $siblings = $wpdb->get_results( $wpdb->prepare( "SELECT id, sort_order FROM {$wpdb->prefix}forum_categories WHERE parent_id=%d ORDER BY sort_order ASC, id ASC", $parent ) ); $ids = array_column( (array) $siblings, 'id' ); $pos = array_search( $move_id, $ids ); if ( $dir === 'up' && $pos > 0 ) { $swap_id = $ids[ $pos - 1 ]; } elseif ( $dir === 'down' && $pos !== false && $pos < count($ids) - 1 ) { $swap_id = $ids[ $pos + 1 ]; } if ( isset( $swap_id ) ) { $so_a = $siblings[$pos]->sort_order; $so_b = $siblings[ $dir === 'up' ? $pos - 1 : $pos + 1 ]->sort_order; if ( $so_a === $so_b ) { $so_b = $dir === 'up' ? $so_a - 1 : $so_a + 1; } $wpdb->update( "{$wpdb->prefix}forum_categories", ['sort_order' => $so_b], ['id' => $move_id] ); $wpdb->update( "{$wpdb->prefix}forum_categories", ['sort_order' => $so_a], ['id' => $swap_id] ); } // Gleiche Seite neu laden (kein redirect_to nötig) $tree = WBF_DB::get_categories_tree(); } if ( isset( $_POST['wbf_save_cat'] ) && check_admin_referer( 'wbf_cat_nonce' ) ) { $data = [ 'parent_id' => (int) ( $_POST['parent_id'] ?? 0 ), 'name' => sanitize_text_field( $_POST['name'] ), 'slug' => sanitize_title( $_POST['name'] ), 'description' => sanitize_textarea_field( $_POST['description'] ), 'icon' => sanitize_text_field( $_POST['icon'] ), 'sort_order' => (int) ( $_POST['sort_order'] ?? 0 ), 'min_role' => sanitize_key( $_POST['min_role'] ?? 'member' ), ]; if ( ! empty( $_POST['cat_id'] ) ) { $wpdb->update( "{$wpdb->prefix}forum_categories", $data, ['id' => (int) $_POST['cat_id']] ); echo '

Gespeichert!

'; } else { $wpdb->insert( "{$wpdb->prefix}forum_categories", $data ); echo '

Erstellt!

'; } } if ( isset( $_GET['delete_cat'] ) && current_user_can( 'manage_options' ) ) { check_admin_referer( 'delete_cat_' . (int) $_GET['delete_cat'] ); $wpdb->delete( "{$wpdb->prefix}forum_categories", ['id' => (int) $_GET['delete_cat']] ); } $tree = WBF_DB::get_categories_tree(); $all = WBF_DB::get_categories_flat(); $edit = isset( $_GET['edit'] ) ? WBF_DB::get_category( (int) $_GET['edit'] ) : null; echo '

Kategorien + Neue Kategorie

'; echo ''; foreach ( $tree as $p ) { $d = wp_nonce_url( "?page=wbf-categories&delete_cat={$p->id}", "delete_cat_{$p->id}" ); $role = WBF_Roles::get( $p->min_role ?? 'member' ); $lockbadge = ( $p->min_role ?? 'member' ) !== 'member' ? " 🔒 " . esc_html( $role['label'] ) . "" : ''; $reorder_p = '' . wp_nonce_field( 'wbf_reorder_nonce', '_wpnonce', true, false ) . '' . '' . '' . '' . '' . '' . wp_nonce_field( 'wbf_reorder_nonce', '_wpnonce', true, false ) . '' . '' . '' . '' . ''; echo ""; 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' ); $reorder_c = '' . wp_nonce_field( 'wbf_reorder_nonce', '_wpnonce', true, false ) . '' . '' . '' . '' . '' . '' . wp_nonce_field( 'wbf_reorder_nonce', '_wpnonce', true, false ) . '' . '' . '' . '' . ''; echo ""; } } echo '
KategorieThreadsMin. RolleAktionen
" . esc_html( $p->name ) . "$lockbadge " . esc_html( $p->thread_count ) . " " . esc_html( $role['label'] ) . " {$reorder_p} Bearbeiten | Löschen
↳ " . esc_html( $c->name ) . " " . esc_html( $c->thread_count ) . " " . esc_html( $crole['label'] ) . " {$reorder_c} Bearbeiten | Löschen
'; $parent_opts = ''; foreach ( $all as $c ) { if ( $edit && $c->id == $edit->id ) continue; $sel = ( $edit && (int) $edit->parent_id === (int) $c->id ) ? ' selected' : ''; $indent = (int) $c->parent_id > 0 ? '  ↳ ' : ''; $parent_opts .= ""; } $role_opts = ''; foreach ( $roles as $k => $r ) { if ( $k === 'banned' || $k === WBF_Roles::SUPERADMIN ) continue; $sel = ( $edit && ( $edit->min_role ?? 'member' ) === $k ) ? ' selected' : ''; $role_opts .= ""; } echo '

' . ( $edit ? 'Bearbeiten: ' . esc_html( $edit->name ) : 'Neue Kategorie' ) . '

'; echo '
'; wp_nonce_field( 'wbf_cat_nonce' ); if ( $edit ) echo ''; echo ' '; echo '
Elternkategorie
Name *
Beschreibung
Icon

z.B. fas fa-home, fas fa-bug

Min. Rolle
Reihenfolge
'; submit_button( $edit ? 'Speichern' : 'Erstellen', 'primary', 'wbf_save_cat' ); echo '
'; } // ── Mitglieder ──────────────────────────────────────────────────────────────── function wbf_admin_members() { $roles = WBF_Roles::get_sorted(); // ── Rolle ändern ────────────────────────────────────────────────────────── if ( isset( $_POST['wbf_change_role'] ) && check_admin_referer( 'wbf_member_role_nonce' ) ) { $uid = (int) $_POST['user_id']; $role = sanitize_key( $_POST['new_role'] ); if ( $uid && $role !== WBF_Roles::SUPERADMIN && array_key_exists( $role, WBF_Roles::get_all() ) ) { $update = ['role' => $role]; if ( $role === 'banned' ) { $update['ban_reason'] = sanitize_textarea_field( $_POST['ban_reason'] ?? '' ); } else { $update['ban_reason'] = ''; } WBF_DB::update_user( $uid, $update ); echo '

Rolle aktualisiert!

'; } } // ── Profil bearbeiten ───────────────────────────────────────────────────── if ( isset( $_POST['wbf_edit_user'] ) && check_admin_referer( 'wbf_edit_user_nonce' ) ) { $uid = (int) $_POST['user_id']; $display_name = sanitize_text_field( $_POST['display_name'] ?? '' ); $email = sanitize_email( $_POST['email'] ?? '' ); $new_password = $_POST['new_password'] ?? ''; if ( $uid && $uid !== 0 ) { $user = WBF_DB::get_user( $uid ); if ( $user && $user->role !== WBF_Roles::SUPERADMIN ) { $update = []; if ( ! empty($display_name) ) $update['display_name'] = $display_name; if ( is_email($email) ) $update['email'] = $email; if ( strlen($new_password) >= 6 ) { $update['password'] = password_hash( $new_password, PASSWORD_DEFAULT ); } if ( ! empty($update) ) { WBF_DB::update_user( $uid, $update ); echo '

Profil von ' . esc_html($user->display_name) . ' aktualisiert!

'; } } } } $members = WBF_DB::get_all_users( 200 ); ?>

Mitglieder

role ); $color = esc_attr( $role['color'] ); $bg = esc_attr( $role['bg_color'] ); $icon = esc_attr( $role['icon'] ?? 'fas fa-user' ); $is_sa = ( $m->role === WBF_Roles::SUPERADMIN ); $ban_reason = esc_attr( $m->ban_reason ?? '' ); $opts = ''; foreach ( $roles as $k => $r ) { if ( $k === WBF_Roles::SUPERADMIN ) continue; $sel = $m->role === $k ? ' selected' : ''; $opts .= ''; } ?>
#NutzerE-Mail Aktuelle RolleBeiträge RegistriertRolle ändern
id ); ?> display_name ); ?>
@username ); ?>
email ); ?> (WP-Admin) post_count ); ?> registered ) ) ); ?> Automatisch (WP-Admin)

Meldung aktualisiert.

'; } } $filter = sanitize_key( $_GET['filter'] ?? 'open' ); $reports = WBF_DB::get_reports( $filter, 100 ); $count = WBF_DB::count_open_reports(); echo '

Meldungen ' . ( $count > 0 ? '' . (int) $count . '' : '' ) . '

'; $tabs = ['open' => 'Offen', 'resolved' => 'Erledigt', 'dismissed' => 'Verworfen', 'all' => 'Alle']; echo ''; if ( empty( $reports ) ) { echo '

Keine Meldungen vorhanden.

'; return; } $reason_labels = [ 'spam' => 'Spam / Werbung', 'harassment' => 'Belästigung', 'inappropriate' => 'Unangemessen', 'misinformation' => 'Fehlinformation', 'off-topic' => 'Offtopic', 'other' => 'Sonstiges', ]; $status_colors = ['open' => '#f59e0b', 'resolved' => '#56cf7e', 'dismissed' => '#6b7a99']; echo ''; foreach ( $reports as $r ) { $reason_label = esc_html( $reason_labels[ $r->reason ] ?? $r->reason ); $preview = esc_html( mb_substr( strip_tags( $r->post_content ?? '' ), 0, 80 ) ); $sc = $status_colors[ $r->status ] ?? '#999'; $status_badge = "" . esc_html( ucfirst( $r->status ) ) . ""; $note_cell = $r->note ? '
' . esc_html( $r->note ) . '' : ''; $base = ['page' => 'wbf-reports', 'report_id' => $r->id, 'filter' => $filter]; if ( $r->status === 'open' ) { $res_url = esc_url( wp_nonce_url( add_query_arg( array_merge( $base, ['report_action' => 'resolved'] ), admin_url('admin.php') ), 'wbf_report_action' ) ); $dis_url = esc_url( wp_nonce_url( add_query_arg( array_merge( $base, ['report_action' => 'dismissed'] ), admin_url('admin.php') ), 'wbf_report_action' ) ); $actions = "✔ Erledigt "; $actions .= "✖ Verwerfen"; } else { $reopen_url = esc_url( wp_nonce_url( add_query_arg( array_merge( $base, ['report_action' => 'open'] ), admin_url('admin.php') ), 'wbf_report_action' ) ); $actions = "↩ Wieder öffnen"; } echo ""; } echo '
#Gemeldet vonGrundVorschauThreadDatumStatusAktionen
" . esc_html( $r->id ) . " " . esc_html( $r->reporter_name ?? '—' ) . "
@" . esc_html( $r->reporter_username ?? '' ) . "
$reason_label$note_cell $preview…
→ Zum Beitrag
" . ( $r->thread_id ? esc_html( mb_substr( $r->thread_title ?? '', 0, 35 ) ) : '—' ) . " " . esc_html( date( 'd.m.Y H:i', strtotime( $r->created_at ) ) ) . " $status_badge $actions
'; } // ── Level-System ────────────────────────────────────────────────────────────── function wbf_admin_levels() { // ── Toggle on/off ──────────────────────────────────────────────────────── if ( isset( $_POST['wbf_toggle_levels'] ) && check_admin_referer( 'wbf_levels_toggle_nonce' ) ) { WBF_Levels::set_enabled( ! empty( $_POST['levels_enabled'] ) ); echo '

Einstellung gespeichert!

'; } // ── Reset ──────────────────────────────────────────────────────────────── if ( isset( $_POST['wbf_reset_levels'] ) && check_admin_referer( 'wbf_levels_reset_nonce' ) ) { WBF_Levels::reset_to_defaults(); echo '

Level auf Standard zurückgesetzt.

'; } // ── Level löschen ──────────────────────────────────────────────────────── if ( isset( $_GET['delete_level'] ) && check_admin_referer( 'delete_level_' . (int) $_GET['delete_level'] ) ) { $idx = (int) $_GET['delete_level']; $levels = WBF_Levels::get_all(); if ( count($levels) > 1 ) { unset( $levels[$idx] ); WBF_Levels::save( array_values($levels) ); echo '

Level gelöscht.

'; } else { echo '

Mindestens ein Level muss vorhanden sein.

'; } } // ── Level speichern (Bearbeiten) ───────────────────────────────────────── if ( isset( $_POST['wbf_save_level'] ) && check_admin_referer( 'wbf_levels_edit_nonce' ) ) { $idx = (int) $_POST['level_index']; $levels = WBF_Levels::get_all(); $levels[$idx] = [ 'min' => max( 0, (int) $_POST['level_min'] ), 'label' => sanitize_text_field( $_POST['level_label'] ), 'icon' => sanitize_text_field( $_POST['level_icon'] ), 'color' => sanitize_hex_color( $_POST['level_color'] ) ?: '#94a3b8', ]; WBF_Levels::save( array_values($levels) ); echo '

Level aktualisiert!

'; } // ── Neues Level erstellen ──────────────────────────────────────────────── if ( isset( $_POST['wbf_create_level'] ) && check_admin_referer( 'wbf_levels_create_nonce' ) ) { $levels = WBF_Levels::get_all(); $levels[] = [ 'min' => max( 0, (int) $_POST['new_level_min'] ), 'label' => sanitize_text_field( $_POST['new_level_label'] ), 'icon' => sanitize_text_field( $_POST['new_level_icon'] ), 'color' => sanitize_hex_color( $_POST['new_level_color'] ) ?: '#94a3b8', ]; WBF_Levels::save( $levels ); echo '

Neues Level erstellt!

'; } $levels = WBF_Levels::get_all(); $enabled = WBF_Levels::is_enabled(); $edit_i = isset( $_GET['edit_level'] ) ? (int) $_GET['edit_level'] : null; $edit_l = ( $edit_i !== null && isset( $levels[$edit_i] ) ) ? $levels[$edit_i] : null; echo '
'; echo '

⭐ Level-System

'; // ── Status-Toggle ──────────────────────────────────────────────────────── $status_color = $enabled ? '#56cf7e' : '#f05252'; $status_label = $enabled ? '✅ Aktiviert' : '❌ Deaktiviert'; echo "
Level-System ist: {$status_label}

Wenn deaktiviert, werden keine Level-Badges im Forum angezeigt.

" . wp_nonce_field( 'wbf_levels_toggle_nonce', '_wpnonce', true, false ) . "
"; // ── Level-Tabelle ──────────────────────────────────────────────────────── echo '

Aktuelle Level

'; echo ''; foreach ( $levels as $i => $l ) { $color = esc_attr( $l['color'] ); $icon = esc_attr( $l['icon'] ); $label = esc_html( $l['label'] ); $del_url = wp_nonce_url( "?page=wbf-levels&delete_level={$i}", "delete_level_{$i}" ); $badge_html = " {$label} "; echo ""; } echo '
# Badge-Vorschau Ab Beiträgen Icon Aktionen
" . ( $i + 1 ) . " {$badge_html} ≥ " . esc_html( $l['min'] ) . " Beiträge {$icon} Bearbeiten " . ( count($levels) > 1 ? " | Löschen" : '' ) . "
'; // ── Reset-Button ───────────────────────────────────────────────────────── echo "
" . wp_nonce_field( 'wbf_levels_reset_nonce', '_wpnonce', true, false ) . "
"; // ── Bearbeiten-Formular ────────────────────────────────────────────────── if ( $edit_l !== null ) { echo '

Level bearbeiten: ' . esc_html( $edit_l['label'] ) . '

'; echo '
'; wp_nonce_field( 'wbf_levels_edit_nonce' ); echo ''; echo wbf_level_form_fields( $edit_l, '' ); echo '
'; submit_button( 'Änderungen speichern', 'primary', 'wbf_save_level' ); echo '

'; } // ── Neues Level erstellen ──────────────────────────────────────────────── echo '

Neues Level erstellen

'; echo '
'; wp_nonce_field( 'wbf_levels_create_nonce' ); echo wbf_level_form_fields( null, 'new_' ); echo '
'; submit_button( '+ Level erstellen', 'primary', 'wbf_create_level' ); echo '
'; echo '
'; } // ── Hilfsformular für Level-Felder ──────────────────────────────────────────── function wbf_level_form_fields( $level, $prefix ) { $min = esc_attr( $level['min'] ?? '' ); $label = esc_attr( $level['label'] ?? '' ); $icon = esc_attr( $level['icon'] ?? 'fas fa-star' ); $color = esc_attr( $level['color'] ?? '#94a3b8' ); return " Ab Beiträgen *

Level ab dieser Beitragsanzahl (0 = für alle).

Bezeichnung * Farbe Icon

FontAwesome 6, z.B. fas fa-crown, fas fa-fire, fas fa-seedling

"; } // ── Export / Import ─────────────────────────────────────────────────────────── function wbf_admin_export() { if ( ! current_user_can('manage_options') ) return; $notice = ''; // Export wird von admin_init verarbeitet (vor HTTP-Header-Output) // ── IMPORT ──────────────────────────────────────────────────────────────── if ( isset( $_POST['wbf_do_import'] ) && check_admin_referer('wbf_import_nonce') ) { if ( empty( $_FILES['import_file']['tmp_name'] ) ) { $notice = ['error', 'Keine Datei hochgeladen.']; } else { $raw = file_get_contents( $_FILES['import_file']['tmp_name'] ); $data = json_decode( $raw, true ); if ( ! $data || ! isset($data['_meta']) ) { $notice = ['error', 'Ungültige Datei — kein gültiges WBF-Backup.']; } else { global $wpdb; $imported = []; $sections = $data['_meta']['sections'] ?? array_keys($data); if ( ! empty($data['settings']) ) { update_option('wbf_settings', $data['settings']); $imported[] = 'Einstellungen'; } if ( ! empty($data['roles']) ) { // Superadmin-Schutz: niemals überschreiben $roles = $data['roles']; unset($roles['superadmin']); $current = get_option('wbf_custom_roles', []); $current['superadmin'] = WBF_Roles::get('superadmin'); update_option('wbf_custom_roles', array_merge($current, $roles)); $imported[] = 'Rollen'; } if ( ! empty($data['levels']) ) { if ( isset($data['levels']['config']) ) update_option('wbf_level_config', $data['levels']['config']); if ( isset($data['levels']['enabled']) ) update_option('wbf_levels_enabled', $data['levels']['enabled']); $imported[] = 'Level'; } if ( ! empty($data['categories']) ) { // Nur importieren wenn Tabelle leer oder Force-Flag gesetzt $force = ! empty($_POST['import_force_cats']); $existing = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}forum_categories"); if ( $existing === 0 || $force ) { if ($force) $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_categories"); foreach ($data['categories'] as $cat) { unset($cat['id']); // auto-increment $wpdb->insert("{$wpdb->prefix}forum_categories", $cat); } $imported[] = 'Kategorien (' . count($data['categories']) . ')'; } else { $imported[] = 'Kategorien übersprungen (bereits vorhanden — „Überschreiben" aktivieren)'; } } if ( ! empty($data['users']) ) { $force = ! empty($_POST['import_force_users']); $count = 0; foreach ($data['users'] as $u) { $exists = $wpdb->get_var($wpdb->prepare( "SELECT id FROM {$wpdb->prefix}forum_users WHERE username=%s OR email=%s", $u['username'], $u['email'] )); if ($exists && !$force) continue; if ($exists && $force) { unset($u['id']); $wpdb->update("{$wpdb->prefix}forum_users", $u, ['id'=>$exists]); } else { unset($u['id']); $u['role'] = ($u['role'] === 'superadmin') ? 'member' : $u['role']; $wpdb->insert("{$wpdb->prefix}forum_users", $u); } $count++; } $imported[] = "Benutzer ($count importiert)"; } if ( ! empty($data['threads']) ) { $force = ! empty($_POST['import_force_threads']); if ($force) { $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_posts"); $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_threads"); $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_thread_tags"); $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_tags"); } foreach ($data['threads'] ?? [] as $t) { $wpdb->insert("{$wpdb->prefix}forum_threads", $t); } foreach ($data['posts'] ?? [] as $p) { $wpdb->insert("{$wpdb->prefix}forum_posts", $p); } // Re-import tags if (!empty($data['thread_tags'])) { $tag_map = []; foreach ($data['thread_tags'] as $tt) { if (!isset($tag_map[$tt['slug']])) { $existing_tag = $wpdb->get_var($wpdb->prepare( "SELECT id FROM {$wpdb->prefix}forum_tags WHERE slug=%s", $tt['slug'] )); if (!$existing_tag) { $wpdb->insert("{$wpdb->prefix}forum_tags", [ 'name'=>$tt['name'],'slug'=>$tt['slug'],'use_count'=>$tt['use_count'] ]); $tag_map[$tt['slug']] = $wpdb->insert_id; } else { $tag_map[$tt['slug']] = $existing_tag; } } $wpdb->replace("{$wpdb->prefix}forum_thread_tags", [ 'thread_id'=>$tt['thread_id'], 'tag_id'=>$tag_map[$tt['slug']] ]); } } $imported[] = 'Threads + Posts (' . count($data['threads']) . ' / ' . count($data['posts'] ?? []) . ')'; } if ( ! empty($data['likes']) ) { $force = ! empty($_POST['import_force_threads']); if ($force) $wpdb->query("DELETE FROM {$wpdb->prefix}forum_likes"); $count = 0; foreach ($data['likes'] as $row) { unset($row['id']); $existing = $wpdb->get_var($wpdb->prepare( "SELECT id FROM {$wpdb->prefix}forum_likes WHERE user_id=%d AND object_id=%d AND object_type=%s", $row['user_id'], $row['object_id'], $row['object_type'] )); if (!$existing) { $wpdb->insert("{$wpdb->prefix}forum_likes", $row); $count++; } } $imported[] = "Likes ($count)"; } if ( ! empty($data['reactions']) ) { $force = ! empty($_POST['import_force_threads']); if ($force) $wpdb->query("DELETE FROM {$wpdb->prefix}forum_reactions"); foreach ($data['reactions'] as $row) { unset($row['id']); $wpdb->replace("{$wpdb->prefix}forum_reactions", $row); } $imported[] = 'Reaktionen (' . count($data['reactions']) . ')'; } if ( ! empty($data['notifications']) ) { $force = ! empty($_POST['import_force_threads']); if ($force) $wpdb->query("DELETE FROM {$wpdb->prefix}forum_notifications"); $count = 0; foreach ($data['notifications'] as $row) { unset($row['id']); $wpdb->insert("{$wpdb->prefix}forum_notifications", $row); $count++; } $imported[] = "Benachrichtigungen ($count)"; } if ( ! empty($data['messages']) ) { $force = ! empty($_POST['import_force_messages']); if ($force) $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_messages"); $count = 0; foreach ($data['messages'] as $row) { unset($row['id']); $wpdb->insert("{$wpdb->prefix}forum_messages", $row); $count++; } $imported[] = "Nachrichten ($count)"; } if ( ! empty($data['reports']) ) { $force = ! empty($_POST['import_force_reports']); if ($force) $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}forum_reports"); $count = 0; foreach ($data['reports'] as $row) { unset($row['id']); $wpdb->insert("{$wpdb->prefix}forum_reports", $row); $count++; } $imported[] = "Meldungen ($count)"; } if ( empty($imported) ) { $notice = ['warning', 'Nichts importiert — Datei enthielt keine gültigen Abschnitte.']; } else { $notice = ['success', '✅ Importiert: ' . implode(', ', $imported) . '. Erstellt: ' . $data['_meta']['exported'] . ' · Site: ' . esc_html($data['_meta']['site'] ?? '?')]; } } } } // ── UI ───────────────────────────────────────────────────────────────────── ?>

Export / Import

Export

Wähle was exportiert werden soll. Die Datei wird als .json heruntergeladen.

['⚙️', 'Einstellungen', 'Forum-Texte, Auto-Logout, Labels'], 'roles' => ['🛡️', 'Rollen', 'Alle Rollen inkl. Berechtigungen & Farben'], 'levels' => ['⭐', 'Level-System', 'Level-Konfiguration & Status'], 'categories' => ['📂', 'Kategorien', 'Alle Kategorien inkl. Hierarchie'], 'users' => ['👥', 'Benutzer', 'Accounts inkl. Passwort-Hashes'], 'threads' => ['💬', 'Threads & Posts', 'Alle Inhalte inkl. Tags'], 'interactions' => ['❤️', 'Likes & Reaktionen', 'Likes, Reaktionen, Benachrichtigungen'], 'messages' => ['✉️', 'Privatnachrichten', 'Alle DM-Konversationen'], 'reports' => ['🚩', 'Meldungen', 'Alle gemeldeten Beiträge'], ]; foreach ($export_options as $key => [$icon, $label, $desc]): ?>
Datei wird sofort heruntergeladen
Import

Lade eine zuvor exportierte .json-Datei hoch.

⚠️ Hinweis: Benutzer-Import enthält Passwort-Hashes. Threads-Import kann bestehende Daten überschreiben. Mache vorher ein Backup.

Überschreiben-Optionen

'Kategorien überschreiben (löscht bestehende)', 'import_force_users' => 'Benutzer aktualisieren (bei gleichem Username)', 'import_force_threads' => 'Threads, Posts, Likes & Reaktionen überschreiben', 'import_force_messages' => 'Privatnachrichten überschreiben', 'import_force_reports' => 'Meldungen überschreiben', ]; foreach ($overwrite_opts as $name => $label): ?>
Nur kompatible WBF-Backups

Export-Inhalte im Überblick