';
+
+ foreach ( $tabs as $tab ) {
+ $tab_title = $tab['title'] ?? 'Allgemein';
+ $rule_count = ! empty( $tab['rules'] ) ? count( $tab['rules'] ) : 0;
+ // Trigger: "regeln:Minecraft"
+ $query = 'regeln:' . $tab_title;
+ $html .= ''
+ . '📂 ' . esc_html( $tab_title )
+ . ' (' . $rule_count . ') '
+ . ' ';
+ }
+
+ $html .= '
';
+ $html .= ''
+ . esc_html( mb_substr( $content_plain, 0, 300 ) ) . '…
';
+ } else {
+ $rendered = ''
+ . wp_kses_post( $content )
+ . '
';
+ }
+
+ $html .= '';
+ foreach ( $tabs as $tab ) {
+ $tab_title = $tab['title'] ?? 'Allgemein';
+ $html .= ''
+ . '📂 ' . esc_html( $tab_title ) . ' ';
+ }
+ $html .= '
';
+
+ return array(
+ 'source' => 'rules',
+ 'title' => '📜 Regelwerk',
+ 'content' => $html,
+ );
+ }
+
+ usort( $matches, function( $a, $b ) { return $b['score'] - $a['score']; } );
+ $top = array_slice( $matches, 0, 3 );
+ $html = '';
+
+ foreach ( $top as $r ) {
+ $content_plain = wp_strip_all_tags( $r['content'] );
+ if ( mb_strlen( $content_plain ) > 300 ) {
+ $rendered = ''
+ . esc_html( mb_substr( $content_plain, 0, 300 ) ) . '…
';
+ } else {
+ $rendered = ''
+ . wp_kses_post( $r['content'] )
+ . '
';
+ }
+
+ $html .= '';
+
+ // ── Tagesaktion nur anzeigen, wenn KEINE Preisabfrage ─────────────────
+ $is_price_query = false;
+ $search = $q_lc;
+ if (preg_match('/\b(was kostet|preis von|wie teuer|wie viel kostet|kosten von|preis für|preis)\b/i', $search)) {
+ $is_price_query = true;
+ }
+ if (!$is_price_query) {
+ $deal = $wpdb->get_row( "SELECT * FROM $t_items WHERE is_daily_deal = 1 AND status = 'publish' LIMIT 1" );
+ if ( $deal ) {
+ $offer = isset( $deal->offer_price ) && $deal->offer_price > 0 ? $deal->offer_price : $deal->price;
+ $img = $img_base . str_replace(':', '_', $deal->item_id) . '.png';
+ $item_link = $shop_url ? esc_url($shop_url) . '#item-' . urlencode($deal->item_id) : '';
+ $lines[] = '
'
+ . '🔥
Tagesaktion: '
+ . '
'
+ . '
' . esc_html( $deal->name ) . '
'
+ . '
'
+ . '' . esc_html( (string) $offer ) . ' ' . esc_html( $currency ) . ' '
+ . ( $deal->price != $offer ? ' ' . esc_html( (string) $deal->price ) . ' ' : '' )
+ . ' '
+ . ( $item_link ? '
→
Zum Item im Shop ' : '' )
+ . '
';
+ }
+ }
+
+ // ── Suchbegriff extrahieren (auch für Preisabfragen) ────────────────
+ // (is_price_query wurde oben schon gesetzt)
+ $search = $q_lc;
+ if ($is_price_query) {
+ // Nur das Item extrahieren
+ $search = preg_replace('/\b(shop|kaufen|kosten|preis|items?|angebot|tagesaktion|daily deal|kategorie|rang|was gibt|zeig|liste|was kostet|preis von|wie teuer|wie viel kostet|kosten von|preis für)\b/i', '', $search);
+ } else {
+ $search = preg_replace('/\b(shop|kaufen|kosten|preis|items?|angebot|tagesaktion|daily deal|kategorie|rang|was gibt|zeig|liste)\b/i', '', $search);
+ }
+ $search = trim(preg_replace('/\s+/', ' ', $search));
+ // Satzzeichen am Anfang/Ende entfernen
+ $search = preg_replace('/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/u', '', $search);
+
+ if (strlen($search) >= 3) {
+ mm_debug_log('Suchbegriff nach Extraktion: ' . $search);
+ // Spezifische Suche (auch für Preisabfragen)
+ $items = $wpdb->get_results($wpdb->prepare(
+ "SELECT * FROM $t_items
+ WHERE status = 'publish' AND (item_title LIKE %s OR name LIKE %s OR item_id LIKE %s)
+ ORDER BY price ASC LIMIT 8",
+ '%' . $wpdb->esc_like($search) . '%',
+ '%' . $wpdb->esc_like($search) . '%',
+ '%' . $wpdb->esc_like($search) . '%'
+ ));
+ mm_debug_log('LIKE-Query: ' . $search . ' | Treffer: ' . count($items));
+
+ if (!empty($items)) {
+ mm_debug_log('LIKE-Query erstes Item: ' . (isset($items[0]) ? json_encode($items[0]) : 'n/a'));
+ // Preisabfrage: Nur das erste Item als Preisantwort
+ if ($is_price_query) {
+ $item = $items[0];
+ $img = $img_base . str_replace(':', '_', $item->item_id) . '.png';
+ $item_link = $shop_url ? esc_url($shop_url) . '#item-' . urlencode($item->item_id) : '';
+ $item_display_name = $item->name ?: ($item->item_title ?: $item->item_id);
+ // Serverliste aufbereiten
+ $server_list = '';
+ if (!empty($item->servers)) {
+ $servers = json_decode($item->servers, true);
+ if (is_array($servers) && count($servers) > 0) {
+ $server_list = '
Verfügbar auf: ' . esc_html(implode(', ', $servers)) . '
';
+ }
+ }
+ $lines[] = '
'
+ . '
🛒 Shop-Item:
'
+ . '
'
+ . '
' . esc_html($item_display_name) . '
'
+ . '
' . esc_html((string)$item->price) . ' ' . esc_html($currency) . '
'
+ . $server_list
+ . '
';
+ } else {
+ $lines[] = '🛒
Gefundene Items: ';
+ foreach ($items as $item) {
+ $img = $img_base . str_replace(':', '_', $item->item_id) . '.png';
+ $item_link = $shop_url ? esc_url($shop_url) . '#item-' . urlencode($item->item_id) : '';
+ $lines[] = '
'
+ . '
' . esc_html($item->item_title) . ' '
+ . ' – ' . esc_html((string)$item->price) . ' ' . esc_html($currency)
+ . ($item_link ? '
[Shop] ' : '');
+ }
+ }
+ } else {
+ // Exakte Suche, falls LIKE nichts findet
+ $item = $wpdb->get_row($wpdb->prepare(
+ "SELECT * FROM $t_items WHERE status = 'publish' AND (name = %s OR item_id = %s OR item_title = %s) LIMIT 1",
+ $search, $search, $search
+ ));
+ mm_debug_log('Exakte Suche: ' . ($item ? json_encode($item) : 'kein Treffer'));
+ // Case-insensitive Fallback, falls nötig
+ if (!$item && !empty($search)) {
+ $item = $wpdb->get_row($wpdb->prepare(
+ "SELECT * FROM $t_items WHERE status = 'publish' AND (name COLLATE utf8_general_ci = %s COLLATE utf8_general_ci OR item_id COLLATE utf8_general_ci = %s COLLATE utf8_general_ci OR item_title COLLATE utf8_general_ci = %s COLLATE utf8_general_ci) LIMIT 1",
+ $search, $search, $search
+ ));
+ mm_debug_log('Case-insensitive Suche: ' . ($item ? json_encode($item) : 'kein Treffer'));
+ }
+ // Fallback: Suchbegriff als Minecraft-ID mit Prefix testen
+ if (!$item && !empty($search) && strpos($search, 'minecraft:') === false) {
+ $mc_id = 'minecraft:' . strtolower(str_replace([' ', '_'], ['_', '_'], $search));
+ $item = $wpdb->get_row($wpdb->prepare(
+ "SELECT * FROM $t_items WHERE status = 'publish' AND (item_id = %s OR item_id COLLATE utf8_general_ci = %s COLLATE utf8_general_ci) LIMIT 1",
+ $mc_id, $mc_id
+ ));
+ mm_debug_log('MC-ID Fallback: ' . $mc_id . ' | ' . ($item ? json_encode($item) : 'kein Treffer'));
+ }
+ if ($item) {
+ mm_debug_log('Gefundenes Item (exakt/fallback): ' . json_encode($item));
+ $img = $img_base . str_replace(':', '_', $item->item_id) . '.png';
+ $item_link = $shop_url ? esc_url($shop_url) . '#item-' . urlencode($item->item_id) : '';
+ $lines[] = '
'
+ . '
'
+ . '
' . esc_html($item->name) . ' '
+ . 'Preis:
' . esc_html((string)$item->price) . ' ' . esc_html($currency) . ' '
+ . ($item_link ? '
[Shop] ' : '')
+ . '
';
+ } else {
+ // Aggressive Fuzzy-Suche als letzter Versuch
+ $all_items = $wpdb->get_results("SELECT * FROM $t_items WHERE status = 'publish'");
+ mm_debug_log('Fuzzy-Suche über alle Items (' . count($all_items) . '): ' . $search);
+ $search_lc = mb_strtolower($search);
+ $fuzzy = null;
+ foreach ($all_items as $it) {
+ if (strpos(mb_strtolower($it->name), $search_lc) !== false
+ || strpos(mb_strtolower($it->item_title), $search_lc) !== false
+ || strpos(mb_strtolower($it->item_id), $search_lc) !== false) {
+ $fuzzy = $it;
+ break;
+ }
+ }
+ mm_debug_log('Fuzzy-Suche Treffer: ' . ($fuzzy ? json_encode($fuzzy) : 'kein Treffer'));
+ if ($fuzzy) {
+ $img = $img_base . str_replace(':', '_', $fuzzy->item_id) . '.png';
+ $item_link = $shop_url ? esc_url($shop_url) . '#item-' . urlencode($fuzzy->item_id) : '';
+ $item_display_name = $fuzzy->name ?: ($fuzzy->item_title ?: $fuzzy->item_id);
+ // Serverliste aufbereiten
+ $server_list = '';
+ if (!empty($fuzzy->servers)) {
+ $servers = json_decode($fuzzy->servers, true);
+ if (is_array($servers) && count($servers) > 0) {
+ $server_list = '
Verfügbar auf: ' . esc_html(implode(', ', $servers)) . '
';
+ }
+ }
+ $lines[] = '
'
+ . '
🛒 Shop-Item:
'
+ . '
'
+ . '
' . esc_html($item_display_name) . '
'
+ . '
' . esc_html((string)$fuzzy->price) . ' ' . esc_html($currency) . '
'
+ . $server_list
+ . '
';
+ } else {
+ $lines[] = 'Kein Item mit „' . esc_html($search) . '“ gefunden.';
+ }
+ }
+ }
+ } else {
+ // Übersicht: Kategorien + Item-Anzahl
+ $total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM $t_items WHERE status = 'publish'" );
+ $lines[] = '🛒
Shop-Übersicht: ' . $total . ' Items verfügbar.';
+
+ $cats = $wpdb->get_results(
+ "SELECT c.name, COUNT(i.id) as cnt
+ FROM $t_cats c
+ LEFT JOIN $t_items i ON i.category_id = c.id AND i.status = 'publish'
+ GROUP BY c.id ORDER BY cnt DESC LIMIT 8"
+ );
+ if ( ! empty( $cats ) ) {
+ $lines[] = '📂
Kategorien: ';
+ foreach ( $cats as $cat ) {
+ $lines[] = ' • ' . esc_html( $cat->name ) . ' (' . intval( $cat->cnt ) . ' Items)';
+ }
+ }
+
+ // Günstigste & teuerste Items
+ $cheapest = $wpdb->get_row( "SELECT item_title, price FROM $t_items WHERE status = 'publish' AND price > 0 ORDER BY price ASC LIMIT 1" );
+ $priciest = $wpdb->get_row( "SELECT item_title, price FROM $t_items WHERE status = 'publish' ORDER BY price DESC LIMIT 1" );
+ if ( $cheapest ) $lines[] = '💚 Günstigstes:
' . esc_html( $cheapest->item_title ) . ' – ' . esc_html( (string) $cheapest->price ) . ' ' . esc_html( $currency );
+ if ( $priciest ) $lines[] = '💎 Teuerstes:
' . esc_html( $priciest->item_title ) . ' – ' . esc_html( (string) $priciest->price ) . ' ' . esc_html( $currency );
+ }
+
+ if ( $shop_url ) {
+ $lines[] = "
";
+ }
+
+ return [
+ 'source' => 'shop',
+ 'title' => '🛒 Shop',
+ 'content' => implode( '
', $lines ),
+ ];
+}
+
+// ============================================================
+// INTENT: TICKET (WP Multi Ticket Pro)
+// ============================================================
+
+function mm_intent_ticket( $q, $bot ) {
+ global $wpdb;
+ $table = $wpdb->prefix . 'wmt_tickets';
+ $table_msg = $wpdb->prefix . 'wmt_messages';
+ $exists = $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) === $table;
+
+ // ── Ticket per Nummer nachschlagen ────────────────────────
+ if ( preg_match( '/#?(\d{3,6})\b/', $q, $m ) && $exists ) {
+ $ticket_id = intval( $m[1] );
+ $ticket = $wpdb->get_row( $wpdb->prepare(
+ "SELECT id, subject, status, category, department, created_at, guest_name, guest_email
+ FROM $table WHERE id = %d",
+ $ticket_id
+ ) );
+
+ if ( $ticket ) {
+ // Letzte Nachricht
+ $last_msg = '';
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_msg'" ) === $table_msg ) {
+ $msg = $wpdb->get_row( $wpdb->prepare(
+ "SELECT message, created_at FROM $table_msg WHERE ticket_id = %d ORDER BY created_at DESC LIMIT 1",
+ $ticket_id
+ ) );
+ if ( $msg ) {
+ $last_msg = '
💬 Letzte Nachricht:
'
+ . esc_html( wp_trim_words( $msg->message, 20, '…' ) )
+ . ' (' . wp_date( 'd.m.Y H:i', strtotime( $msg->created_at ) ) . ') ';
+ }
+ }
+
+ $lines = [
+ '🎫 Ticket
#' . $ticket->id . ' ',
+ '📋 Betreff:
' . esc_html( $ticket->subject ) . ' ',
+ '📌 Status:
' . esc_html( $ticket->status ) . ' ',
+ '🏷️ Kategorie: ' . esc_html( $ticket->category ?: '–' ),
+ ];
+ if ( ! empty( $ticket->department ) ) {
+ $lines[] = '🏢 Abteilung: ' . esc_html( $ticket->department );
+ }
+ if ( ! empty( $ticket->guest_name ) ) {
+ $lines[] = '👤 Von: ' . esc_html( $ticket->guest_name );
+ }
+ $lines[] = '📅 Erstellt: ' . wp_date( 'd.m.Y \u\m H:i', strtotime( $ticket->created_at ) );
+ if ( $last_msg ) $lines[] = $last_msg;
+
+ return [
+ 'source' => 'ticket',
+ 'title' => '🎫 Ticket #' . $ticket->id,
+ 'content' => implode( '
', $lines ),
+ ];
+ } else {
+ return [
+ 'source' => 'ticket',
+ 'title' => '🎫 Ticket nicht gefunden',
+ 'content' => 'Ticket
#' . $ticket_id . ' existiert nicht.',
+ ];
+ }
+ }
+
+ // ── Allgemeine Ticket-Übersicht ────────────────────────────
+ $lines = [];
+
+ if ( $exists ) {
+ $open = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $table WHERE status NOT LIKE %s", '%Geschlossen%' ) );
+ $closed = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $table WHERE status LIKE %s", '%Geschlossen%' ) );
+ $total = $open + $closed;
+
+ $lines[] = '📊 Gesamt:
' . $total . ' Tickets · Offen:
' . $open . ' · Geschlossen:
' . $closed . ' ';
+
+ // Kategorien anzeigen
+ $cats = $wpdb->get_results(
+ "SELECT COALESCE(category, 'Keine Kategorie') as cat, COUNT(*) as cnt
+ FROM $table GROUP BY category ORDER BY cnt DESC LIMIT 5"
+ );
+ if ( ! empty( $cats ) ) {
+ $cat_parts = [];
+ foreach ( $cats as $c ) {
+ $cat_parts[] = esc_html( $c->cat ) . ' (' . intval( $c->cnt ) . ')';
+ }
+ $lines[] = '📂
Kategorien: ' . implode( ' · ', $cat_parts );
+ }
+ }
+
+ $ticket_url = $bot['url_tickets'] ?? '';
+ if ( $ticket_url ) {
+ $lines[] = "→
Neues Ticket erstellen ";
+ $lines[] = '
Oder gib eine Ticket-Nummer ein, z.B.: #1234 ';
+ } else {
+ $lines[] = 'Bitte nutze das Support-Formular auf unserer Website.';
+ }
+
+ return [
+ 'source' => 'ticket',
+ 'title' => '🎫 Support-Ticket',
+ 'content' => implode( '
', $lines ),
+ ];
+}
+
+// ============================================================
+// INTENT: FORUM (WP Business Forum)
+// ============================================================
+
+function mm_intent_forum( $q ) {
+ // Nur aktiv wenn WBF installiert UND URL im Backend gesetzt
+ $bot = get_option( 'mm_bot_data', [] );
+ if ( ! class_exists( 'WBF_DB' ) ) return null;
+ if ( empty( $bot['url_forum'] ) ) return null;
+
+ global $wpdb;
+
+ $forum_url = esc_url( $bot['url_forum'] );
+ $q_lc = mb_strtolower( $q );
+
+ // Tabellen prüfen — fehlen sie, früh abbrechen statt hängen
+ $t_tbl = $wpdb->prefix . 'forum_threads';
+ $p_tbl = $wpdb->prefix . 'forum_posts';
+ $u_tbl = $wpdb->prefix . 'forum_users';
+ $c_tbl = $wpdb->prefix . 'forum_categories';
+
+ $tables_ok = (
+ $wpdb->get_var( "SHOW TABLES LIKE '$t_tbl'" ) === $t_tbl &&
+ $wpdb->get_var( "SHOW TABLES LIKE '$u_tbl'" ) === $u_tbl &&
+ $wpdb->get_var( "SHOW TABLES LIKE '$c_tbl'" ) === $c_tbl
+ );
+
+ // ── Sub-Intent: Registrierung ─────────────────────────────
+ if ( preg_match( '/\b(registrier(en|ung)?|konto erstellen|account erstellen|sign.?up|einschreiben)\b/i', $q ) ) {
+ $lines = [];
+ if ( $tables_ok ) {
+ try {
+ $reg_mode = get_option( 'wbf_settings', [] )['registration_mode'] ?? 'open';
+ $member_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM $u_tbl WHERE role != 'banned'" );
+
+ $lines[] = '📝
Registrierung: ';
+ if ( $reg_mode === 'disabled' ) {
+ $lines[] = '❌ Die Registrierung ist derzeit
deaktiviert .';
+ } elseif ( $reg_mode === 'invite' ) {
+ $lines[] = '🔒 Das Forum nutzt
Einladungscodes . Du benötigst einen gültigen Code.';
+ } else {
+ $lines[] = '✅ Die Registrierung ist
offen — jederzeit möglich.';
+ }
+ if ( $member_count > 0 ) {
+ $lines[] = '
👥 Bereits ' . $member_count . ' Mitglieder dabei. ';
+ }
+ } catch ( \Throwable $e ) {
+ $lines[] = '📝 Registrierung verfügbar.';
+ }
+ } else {
+ $lines[] = '📝
Registrierung: ';
+ $lines[] = 'Erstelle deinen Account direkt im Forum.';
+ }
+ $lines[] = "→
Zum Forum & Registrierung ";
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum-Registrierung',
+ 'content' => implode( '
', $lines ),
+ ];
+ }
+
+ // ── Sub-Intent: Login / Passwort ──────────────────────────
+ if ( preg_match( '/\b(login|einloggen|passwort vergessen|passwort.?reset|zugangsdaten)\b/i', $q ) ) {
+ $lines = [];
+ $lines[] = '🔑
Forum-Login: ';
+ $lines[] = "→
Zum Forum & Login ";
+ if ( preg_match( '/passwort/i', $q ) ) {
+ $lines[] = '
🔓
Passwort vergessen? ';
+ $lines[] = 'Klicke auf der Login-Seite auf
„Passwort vergessen" .';
+ }
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum-Login',
+ 'content' => implode( '
', $lines ),
+ ];
+ }
+
+ // ── Sub-Intent: Profil ────────────────────────────────────
+ if ( preg_match( '/\b(profil|mein konto|mein account|avatar|signatur|forum rang|forum level)\b/i', $q ) ) {
+ $lines = [];
+ $lines[] = '👤
Dein Forum-Profil enthält:';
+ $lines[] = ' • Anzeigename, Avatar & Signatur';
+ if ( class_exists( 'WBF_Levels' ) && WBF_Levels::is_enabled() ) {
+ $lines[] = ' • Level-System (basiert auf Beitragsanzahl)';
+ }
+ $lines[] = ' • Rollen-Badge, Beitragsanzahl & Registrierungsdatum';
+ $lines[] = "→
Zum Forum → Profil öffnen ";
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum-Profil',
+ 'content' => implode( '
', $lines ),
+ ];
+ }
+
+ // ── Sub-Intent: Nachrichten / DM ──────────────────────────
+ if ( preg_match( '/\b(direktnachricht|forum nachricht|forum inbox|pn schreiben|privat.?nachricht)\b/i', $q ) ) {
+ $lines = [];
+ $lines[] = '✉️
Direktnachrichten im Forum:';
+ $lines[] = 'Du kannst eingeloggten Mitgliedern direkt Nachrichten schreiben.';
+ $lines[] = "→
Forum öffnen → Postfach ";
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum-Nachrichten',
+ 'content' => implode( '
', $lines ),
+ ];
+ }
+
+ // ── Sub-Intent: Thread erstellen ──────────────────────────
+ if ( preg_match( '/\b(neuen thread|thread erstellen|beitrag erstellen|topic erstellen|im forum schreiben|im forum posten)\b/i', $q ) ) {
+ $lines = [];
+ $lines[] = '✏️
Neuen Thread erstellen: ';
+ $lines[] = '① Melde dich im Forum an.';
+ $lines[] = '② Wähle die passende Kategorie.';
+ $lines[] = '③ Klicke auf
„Neuen Thread" und fülle Titel & Inhalt aus.';
+ $lines[] = "→
Forum öffnen ";
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Thread erstellen',
+ 'content' => implode( '
', $lines ),
+ ];
+ }
+
+ // ── Suchbegriff extrahieren ────────────────────────────────
+ $search = preg_replace( '/\b(forum|diskussion|thread|thema|beitrag|post|kategorie|suche?)\b/i', '', $q );
+ $search = trim( preg_replace( '/\s+/', ' ', $search ) );
+
+ // ── Thread-Suche ──────────────────────────────────────────
+ if ( strlen( $search ) >= 3 && $tables_ok ) {
+ try {
+ $threads = $wpdb->get_results( $wpdb->prepare(
+ "SELECT t.id, t.title, t.slug, t.reply_count, t.view_count, t.is_pinned,
+ c.name as cat_name
+ FROM {$t_tbl} t
+ LEFT JOIN {$c_tbl} c ON t.category_id = c.id
+ WHERE t.title LIKE %s AND t.deleted_at IS NULL
+ ORDER BY t.is_pinned DESC, t.created_at DESC LIMIT 5",
+ '%' . $wpdb->esc_like( $search ) . '%'
+ ) );
+
+ if ( ! empty( $threads ) ) {
+ $html = '';
+ foreach ( $threads as $t ) {
+ $t_url = $forum_url . '?thread=' . esc_attr( $t->slug );
+ $pin = $t->is_pinned ? '📌 ' : '';
+ $meta = [];
+ if ( $t->reply_count > 0 ) $meta[] = $t->reply_count . ' Antworten';
+ if ( $t->view_count > 0 ) $meta[] = $t->view_count . ' Aufrufe';
+ $title_short = mb_strlen( $t->title ) > 50 ? mb_substr( $t->title, 0, 50 ) . '…' : $t->title;
+ $html .= '
';
+ $html .= $pin . '
' . esc_html( $title_short ) . ' ';
+ if ( $t->cat_name ) $html .= '
· ' . esc_html( $t->cat_name ) . ' ';
+ if ( ! empty( $meta ) ) $html .= '
' . implode( ' · ', $meta ) . ' ';
+ $html .= '
';
+ }
+ $html .= "
→
Alle Threads im Forum ";
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum – ' . count( $threads ) . ' Treffer',
+ 'content' => $html,
+ ];
+ }
+
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum',
+ 'content' => 'Kein Thread zu
' . esc_html( $search ) . ' gefunden.
'
+ . "→
Forum öffnen & selbst suchen ",
+ ];
+ } catch ( \Throwable $e ) {
+ // Bei DB-Fehler: einfach Übersicht zeigen
+ }
+ }
+
+ // ── Allgemeine Übersicht mit Live-Statistiken ──────────────
+ $lines = [];
+
+ if ( $tables_ok ) {
+ try {
+ $total_threads = (int) $wpdb->get_var( "SELECT COUNT(*) FROM $t_tbl WHERE deleted_at IS NULL" );
+ $total_posts = (int) $wpdb->get_var( "SELECT COUNT(*) FROM $p_tbl WHERE deleted_at IS NULL" );
+ $total_members = (int) $wpdb->get_var( "SELECT COUNT(*) FROM $u_tbl WHERE role != 'banned'" );
+ $online_count = (int) $wpdb->get_var(
+ "SELECT COUNT(*) FROM $u_tbl WHERE last_active >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)"
+ );
+
+ $stat_parts = [];
+ if ( $total_threads > 0 ) $stat_parts[] = '
' . $total_threads . ' Threads';
+ if ( $total_posts > 0 ) $stat_parts[] = '
' . $total_posts . ' Beiträge';
+ if ( $total_members > 0 ) $stat_parts[] = '
' . $total_members . ' Mitglieder';
+ if ( ! empty( $stat_parts ) ) {
+ $lines[] = '📊 ' . implode( ' · ', $stat_parts );
+ }
+
+ $online_icon = $online_count > 0 ? '🟢' : '⚫';
+ $lines[] = $online_icon . ' ' . ( $online_count > 0
+ ? '
' . $online_count . ' Mitglied' . ( $online_count > 1 ? 'er' : '' ) . ' gerade online'
+ : 'Aktuell niemand aktiv' );
+
+ // Kategorien
+ $cats = $wpdb->get_results(
+ "SELECT c.name, c.slug, COUNT(t.id) as thread_count
+ FROM {$c_tbl} c
+ LEFT JOIN {$t_tbl} t ON t.category_id = c.id AND t.deleted_at IS NULL
+ WHERE c.parent_id = 0
+ GROUP BY c.id ORDER BY c.sort_order ASC LIMIT 6"
+ );
+ if ( ! empty( $cats ) ) {
+ $lines[] = '
📂
Kategorien: ';
+ foreach ( $cats as $cat ) {
+ $c_url = $forum_url . '?cat=' . esc_attr( $cat->slug );
+ $count = $cat->thread_count > 0 ? '
(' . (int) $cat->thread_count . ') ' : '';
+ $lines[] = ' →
'
+ . esc_html( $cat->name ) . ' ' . $count;
+ }
+ }
+
+ // Neueste Threads
+ $recent = $wpdb->get_results(
+ "SELECT t.title, t.slug, t.reply_count
+ FROM {$t_tbl} t
+ WHERE t.deleted_at IS NULL AND t.is_pinned = 0
+ ORDER BY t.created_at DESC LIMIT 3"
+ );
+ if ( ! empty( $recent ) ) {
+ $lines[] = '
🆕
Neueste Threads: ';
+ foreach ( $recent as $r ) {
+ $t_url = $forum_url . '?thread=' . esc_attr( $r->slug );
+ $title_short = mb_strlen( $r->title ) > 50 ? mb_substr( $r->title, 0, 50 ) . '…' : $r->title;
+ $replies = $r->reply_count > 0 ? '
(' . (int) $r->reply_count . ' Antw.) ' : '';
+ $lines[] = ' →
'
+ . esc_html( $title_short ) . ' ' . $replies;
+ }
+ }
+ } catch ( \Throwable $e ) {
+ $lines[] = '⚠️ Forum-Daten konnten nicht geladen werden.';
+ }
+ }
+
+ $lines[] = ( ! empty( $lines ) ? '
' : '' )
+ . "→
Forum öffnen ";
+
+ return [
+ 'source' => 'forum',
+ 'title' => '💬 Forum',
+ 'content' => implode( '
', $lines ),
+ ];
+}
+
+// ============================================================
+// INTENT: GALERIE (MC MultiServer Gallery PRO)
+// ============================================================
+
+function mm_intent_gallery( $bot, $q_lc = '' ) {
+ $gallery_url = ! empty( $bot['url_gallery'] ) ? $bot['url_gallery'] : home_url( '/galerie' );
+
+ // ── Erkennen ob Upload-Frage ──────────────────────────────
+ $is_upload_query = (bool) preg_match(
+ '/hochlad|upload|uploaden|verifizier|verify|token|bild teilen|bilder teilen|wie.*bild|anleitung.*galerie/i',
+ $q_lc
+ );
+
+ $lines = [];
+
+ // ── 1. Galerie-Link ──────────────────────────────────────
+ $lines[] = "📷 →
Galerie öffnen ";
+
+ // ── 2. Upload-Anleitung (bei Upload-Frage oder allgemein) ─
+ if ( $is_upload_query ) {
+ $lines[] = '
';
+ $lines[] = '📤
Bilder hochladen – so geht\'s: ';
+ $lines[] = '①
Galerie öffnen und auf
„Bilder hochladen" klicken.';
+ $lines[] = '② Deinen
Minecraft-Namen eingeben und den Server wählen →
Session starten .';
+ $lines[] = '③ Im Spiel den Befehl
/verify [token] eingeben, um dich zu verifizieren.';
+ $lines[] = '④
Screenshots auswählen (optional Album anlegen) → hochladen ✓';
+ $lines[] = '
💡 Der Verify-Token ist 5 Minuten gültig. Du musst dazu online auf dem Server sein. ';
+ } else {
+ // Kurz-Hinweis auf Upload auch bei allgemeiner Galerie-Frage
+ $lines[] = "🖼️ Du kannst eigene Screenshots direkt auf der Galerie-Seite hochladen.";
+ }
+
+ // ── 3. Bild des Tages ────────────────────────────────────
+ if ( post_type_exists( 'mc_gallery' ) ) {
+ $today_key = 'mc_daily_image_' . gmdate( 'Y-m-d' );
+ $image_id = get_transient( $today_key );
+
+ if ( $image_id && wp_attachment_is_image( $image_id ) ) {
+ $img = wp_get_attachment_image_src( $image_id, 'medium' );
+ $full = wp_get_attachment_image_src( $image_id, 'full' );
+ $meta = get_post( $image_id );
+ $uploader = '';
+
+ // Spielername aus Galerie-Post-Meta holen
+ if ( $meta && $meta->post_parent ) {
+ $player = get_post_meta( $meta->post_parent, 'mc_player', true );
+ if ( $player ) {
+ $uploader = '
von ' . esc_html( $player ) . ' ';
+ }
+ }
+
+ if ( $img ) {
+ $lines[] = '
';
+ $lines[] = '🌟
Bild des Tages' . $uploader . ': ';
+ $lines[] = "
"
+ . " "
+ . " ";
+ }
+ } else {
+ // Kein Tagesbild gecacht → Hinweis
+ $lines[] = '
📅 Heute noch kein Bild des Tages verfügbar. ';
+ }
+
+ // Galerie-Statistik
+ $count = wp_count_posts( 'mc_gallery' );
+ if ( $count && $count->publish > 0 ) {
+ $lines[] = '
📁 ' . intval( $count->publish ) . ' Galerie(n) auf dem Server. ';
+ }
+ }
+
+ return [
+ 'source' => 'gallery',
+ 'title' => $is_upload_query ? '📤 Galerie & Upload' : '📷 Galerie',
+ 'content' => implode( '
', $lines ),
+ ];
+}
+
+// ============================================================
+// INTENT: FAQ (Custom Post Type 'faq')
+// ============================================================
+
+function mm_intent_faq( $q ) {
+ if ( ! post_type_exists( 'faq' ) ) return null;
+
+ $search = preg_replace( '/\b(faq|häufig|frage|oft gefragt)\b/i', '', $q );
+ $search = trim( $search );
+
+ $results = get_posts( [
+ 'post_type' => 'faq',
+ 'post_status' => 'publish',
+ 's' => strlen( $search ) >= 3 ? $search : '',
+ 'posts_per_page' => 4,
+ 'orderby' => 'relevance',
+ ] );
+
+ if ( empty( $results ) ) return null;
+
+ $html = '
';
+ foreach ( $results as $post ) {
+ $title = esc_html( $post->post_title );
+ $content = apply_filters( 'the_content', $post->post_content );
+ $html .= '
';
+ $html .= '
' . $title . '
';
+ $html .= '
' . $content . '
';
+ $html .= '
';
+ }
+ $html .= '
';
+
+ return [
+ 'source' => 'faq',
+ 'title' => 'FAQ',
+ 'content' => $html,
+ ];
+}
+
+// ============================================================
+// SPIELER-NAME EXTRAHIEREN
+// ============================================================
+
+function mm_extract_player_name( $q ) {
+ // Explizit: "von Steve", "spieler Steve", "für Steve"
+ if ( preg_match( '/(?:von|spieler|name|für|player|ban.*?von|bann.*?von)[:\s]+([A-Za-z0-9_]{3,16})/iu', $q, $m ) ) {
+ return $m[1];
+ }
+ // "Steve ist gebannt", "ist Steve gebannt"
+ if ( preg_match( '/\b([A-Za-z0-9_]{3,16})\s+ist\s+(gebannt|gesperrt|online|offline)/i', $q, $m ) ) {
+ return $m[1];
+ }
+ // "bin ich" → kein Name (eingeloggter User, kein Minecraft-Login hier)
+ if ( preg_match( '/\b(bin ich|ich bin|mein ban|mein status)\b/i', $q ) ) {
+ return '';
+ }
+ // Allgemein: letztes kapitalisiertes Wort als Spielername (MC-Namen beginnen meist groß)
+ if ( preg_match_all( '/\b([A-Z][A-Za-z0-9_]{2,15})\b/', $q, $m ) ) {
+ $stop = [ 'Minecraft', 'Wiki', 'Forum', 'FAQ', 'Shop', 'Discord', 'Ban', 'Mute',
+ 'Kick', 'Warn', 'Spielzeit', 'Playtime', 'Galerie', 'Ticket', 'Support' ];
+ foreach ( array_reverse( $m[1] ) as $candidate ) {
+ if ( ! in_array( $candidate, $stop, true ) ) {
+ return $candidate;
+ }
+ }
+ }
+ return '';
+}
+
+// ============================================================
+// FALLBACK
+// ============================================================
+
+function mm_fallback_response( $bot ) {
+ $hints = [
+ '🖥️
Server – z.B. "Wie ist die Server-IP?"',
+ ];
+ if ( ! empty( $bot['url_rules'] ) ) $hints[] = '📜
Regeln – z.B. "Ist PvP erlaubt?"';
+ if ( ! empty( $bot['url_player_history'] ) ) $hints[] = '👤
Spieler-Info – z.B. "Spielzeit von Steve"';
+ if ( ! empty( $bot['litebans_dashboard_url'] ) || ! empty( get_option( 'wp_litebans_pro_settings', [] )['db_name'] ) )
+ $hints[] = '🔨
Ban-Status – z.B. "Ist Steve gebannt?"';
+ if ( ! empty( $bot['url_wiki'] ) ) $hints[] = '📖
Wiki – z.B. "Wiki Befehle"';
+ if ( ! empty( $bot['url_gallery'] ) ) $hints[] = '📷
Galerie – z.B. "Zeig die Galerie"';
+ if ( ! empty( $bot['url_shop'] ) ) $hints[] = '🛒
Shop – z.B. "Was kostet ein Diamantschwert?"';
+ if ( ! empty( $bot['url_tickets'] ) ) $hints[] = '🎫
Ticket – z.B. "Ticket erstellen"';
+
+ return [
+ 'source' => 'fallback',
+ 'title' => '❓ Ich habe dazu keine Antwort',
+ 'content' => 'Versuche es mit einem dieser Themen:
' . implode( '
', $hints ),
+ ];
+}
+
+// ============================================================
+// RESPONSE BUILDER
+// Alle Part-Arrays zu einem einzigen formatierten HTML-String
+// zusammenführen.
+// ============================================================
+
+function mm_build_response( $parts ) {
+ if ( count( $parts ) === 1 ) {
+ $p = $parts[0];
+ return [
+ 'reply' => isset( $p['title'] )
+ ? "
{$p['title']} {$p['content']}"
+ : $p['content'],
+ 'parts' => $parts,
+ ];
+ }
+
+ $blocks = [];
+ foreach ( $parts as $p ) {
+ $block = isset( $p['title'] ) ? "
{$p['title']} " : '';
+ $block .= $p['content'];
+ $blocks[] = $block;
+ }
+
+ return [
+ 'reply' => implode( '
', $blocks ),
+ 'parts' => $parts,
+ ];
}
\ No newline at end of file
diff --git a/Minecraft-Modern-Theme/inc/assistant-widget.php b/Minecraft-Modern-Theme/inc/assistant-widget.php
index 5bdc670..f461f11 100644
--- a/Minecraft-Modern-Theme/inc/assistant-widget.php
+++ b/Minecraft-Modern-Theme/inc/assistant-widget.php
@@ -1,913 +1,913 @@
- 'mm_bot_sanitize_settings',
- ] );
-} );
-
-function mm_bot_sanitize_settings( $input ) {
- $clean = [];
-
- $text_fields = [ 'server_ip', 'server_ver', 'server_specs', 'bot_name', 'welcome' ];
- $url_fields = [
- 'url_wiki', 'url_rules', 'url_tickets', 'url_faq',
- 'url_team', 'url_shop', 'url_gallery', 'url_player_history',
- 'url_forum', 'link_discord', 'litebans_dashboard_url',
- ];
-
- foreach ( $text_fields as $f ) {
- $clean[ $f ] = isset( $input[ $f ] ) ? sanitize_text_field( $input[ $f ] ) : '';
- }
- foreach ( $url_fields as $f ) {
- $clean[ $f ] = isset( $input[ $f ] ) ? esc_url_raw( $input[ $f ] ) : '';
- }
-
- $clean['qa'] = [];
- if ( ! empty( $input['qa'] ) && is_array( $input['qa'] ) ) {
- foreach ( $input['qa'] as $item ) {
- if ( empty( $item['keys'] ) ) continue;
- $clean['qa'][] = [
- 'keys' => sanitize_text_field( $item['keys'] ),
- 'val' => wp_kses_post( $item['val'] ),
- ];
- }
- }
-
- return $clean;
-}
-
-// =========================================================================
-// 2. ADMIN-SEITE
-// =========================================================================
-
-// BUG-FIX: Funktion außerhalb von mm_render_bot_admin() definieren.
-// Innerhalb einer Funktion definierte benannte Funktionen erzeugen einen
-// Fatal Error "Cannot redeclare", wenn die äußere Funktion jemals ein
-// zweites Mal ausgeführt wird (z.B. durch AJAX, REST, bestimmte Plugins).
-if ( ! function_exists( 'mm_find_page_by_shortcode' ) ) :
-function mm_find_page_by_shortcode( $shortcodes ) {
- global $wpdb;
- $conditions = [];
- foreach ( (array) $shortcodes as $sc ) {
- $conditions[] = $wpdb->prepare( 'post_content LIKE %s', '%[' . $wpdb->esc_like( $sc ) . '%' );
- }
- if ( empty( $conditions ) ) return '';
- $where = implode( ' OR ', $conditions );
- $page = $wpdb->get_row(
- "SELECT ID FROM {$wpdb->posts}
- WHERE post_status = 'publish'
- AND post_type IN ('page','post')
- AND ({$where})
- LIMIT 1"
- );
- return $page ? get_permalink( $page->ID ) : '';
-}
-endif;
-
-function mm_render_bot_admin() {
- $data = get_option( 'mm_bot_data', [] );
- ?>
-
-
-
- '🖥️ Server-Status', 'q' => 'server status' ];
- }
-
- // Regeln – nur wenn URL im Backend gesetzt
- if ( ! empty( $data['url_rules'] ) ) {
- $quick[] = [ 'label' => '📜 Regelwerk', 'q' => 'regeln' ];
- }
-
- // Wiki – nur wenn URL im Backend gesetzt
- if ( ! empty( $data['url_wiki'] ) ) {
- $quick[] = [ 'label' => '📖 Wiki', 'q' => 'wiki' ];
- }
-
- // Shop – nur wenn URL im Backend gesetzt
- global $wpdb;
- if ( ! empty( $data['url_shop'] ) ) {
- $quick[] = [ 'label' => '🛒 Shop', 'q' => 'shop' ];
- }
-
- // Ticket / Support – nur wenn URL im Backend gesetzt
- if ( ! empty( $data['url_tickets'] ) ) {
- $quick[] = [ 'label' => '🎫 Support-Ticket', 'q' => 'ticket erstellen' ];
- }
-
- // Forum
- if ( class_exists( 'WBF_DB' ) && ! empty( $data['url_forum'] ) ) {
- $quick[] = [ 'label' => '💬 Forum', 'q' => 'forum' ];
- }
-
- // Galerie – nur wenn URL im Backend gesetzt
- if ( ! empty( $data['url_gallery'] ) ) {
- $quick[] = [ 'label' => '📷 Galerie', 'q' => 'galerie' ];
- }
-
- // Ban-Status
- $lb = get_option( 'wp_litebans_pro_settings', [] );
- if ( ! empty( $lb['db_name'] ) ) {
- $quick[] = [ 'label' => '🔨 Strafen prüfen', 'q' => 'meine strafen' ];
- }
-
- // Spieler-History – nur wenn URL im Backend gesetzt
- if ( ! empty( $data['url_player_history'] ) ) {
- $quick[] = [ 'label' => '⏱️ Spielzeit', 'q' => 'spielzeit' ];
- }
-
- // Discord
- if ( ! empty( $data['link_discord'] ) ) {
- $quick[] = [ 'label' => '💬 Discord', 'q' => 'discord' ];
- }
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ➤
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'mm_bot_sanitize_settings',
+ ] );
+} );
+
+function mm_bot_sanitize_settings( $input ) {
+ $clean = [];
+
+ $text_fields = [ 'server_ip', 'server_ver', 'server_specs', 'bot_name', 'welcome' ];
+ $url_fields = [
+ 'url_wiki', 'url_rules', 'url_tickets', 'url_faq',
+ 'url_team', 'url_shop', 'url_gallery', 'url_player_history',
+ 'url_forum', 'link_discord', 'litebans_dashboard_url',
+ ];
+
+ foreach ( $text_fields as $f ) {
+ $clean[ $f ] = isset( $input[ $f ] ) ? sanitize_text_field( $input[ $f ] ) : '';
+ }
+ foreach ( $url_fields as $f ) {
+ $clean[ $f ] = isset( $input[ $f ] ) ? esc_url_raw( $input[ $f ] ) : '';
+ }
+
+ $clean['qa'] = [];
+ if ( ! empty( $input['qa'] ) && is_array( $input['qa'] ) ) {
+ foreach ( $input['qa'] as $item ) {
+ if ( empty( $item['keys'] ) ) continue;
+ $clean['qa'][] = [
+ 'keys' => sanitize_text_field( $item['keys'] ),
+ 'val' => wp_kses_post( $item['val'] ),
+ ];
+ }
+ }
+
+ return $clean;
+}
+
+// =========================================================================
+// 2. ADMIN-SEITE
+// =========================================================================
+
+// BUG-FIX: Funktion außerhalb von mm_render_bot_admin() definieren.
+// Innerhalb einer Funktion definierte benannte Funktionen erzeugen einen
+// Fatal Error "Cannot redeclare", wenn die äußere Funktion jemals ein
+// zweites Mal ausgeführt wird (z.B. durch AJAX, REST, bestimmte Plugins).
+if ( ! function_exists( 'mm_find_page_by_shortcode' ) ) :
+function mm_find_page_by_shortcode( $shortcodes ) {
+ global $wpdb;
+ $conditions = [];
+ foreach ( (array) $shortcodes as $sc ) {
+ $conditions[] = $wpdb->prepare( 'post_content LIKE %s', '%[' . $wpdb->esc_like( $sc ) . '%' );
+ }
+ if ( empty( $conditions ) ) return '';
+ $where = implode( ' OR ', $conditions );
+ $page = $wpdb->get_row(
+ "SELECT ID FROM {$wpdb->posts}
+ WHERE post_status = 'publish'
+ AND post_type IN ('page','post')
+ AND ({$where})
+ LIMIT 1"
+ );
+ return $page ? get_permalink( $page->ID ) : '';
+}
+endif;
+
+function mm_render_bot_admin() {
+ $data = get_option( 'mm_bot_data', [] );
+ ?>
+
+
Bot-Zentrale
+
+
+
+
+
+
+
+
+
+
+
+
2. Bot-Einstellungen
+
+
+
+
+
+
3. Wichtige Links
+
+ 💡 Wenn eine Seite mit dem passenden Shortcode gefunden wird, erscheint ein „Vorschlag übernehmen" -Button.
+
+
+ mm_find_page_by_shortcode( ['wmw_wiki', 'wmw_search', 'wmw_article'] ),
+ 'url_rules' => mm_find_page_by_shortcode( ['mrp_rules', 'mc_rules', 'multi_rules'] ),
+ 'url_tickets' => mm_find_page_by_shortcode( ['wmtp_tickets', 'wm_tickets', 'multi_ticket'] ),
+ 'url_shop' => mm_find_page_by_shortcode( ['wis_shop', 'ingame_shop', 'wis_items'] ),
+ 'url_gallery' => mm_find_page_by_shortcode( ['mc_gallery', 'mc_gallery_overview', 'mc_gallery_upload', 'mc_gallery_all_albums'] ),
+ 'url_faq' => mm_find_page_by_shortcode( ['faq_list', 'faq', 'faq_page'] ),
+ 'url_player_history' => mm_find_page_by_shortcode( ['mc_player_history', 'mc_players', 'player_history'] ),
+ 'url_forum' => mm_find_page_by_shortcode( ['business_forum'] ),
+ 'litebans_dashboard_url' => mm_find_page_by_shortcode( ['litebans_dashboard', 'litebans', 'wp_litebans'] ),
+ ];
+
+ $links = [
+ 'url_wiki' => [ 'label' => '📖 Wiki-URL', 'plugin' => 'WP Multi Wiki', 'active' => post_type_exists( 'wmw_article' ) ],
+ 'url_rules' => [ 'label' => '📜 Regelwerk-URL', 'plugin' => 'Multi Rules', 'active' => function_exists( 'mrp_get_plugin_version' ) ],
+ 'url_tickets' => [ 'label' => '🎫 Ticket/Support-URL', 'plugin' => 'WP Multi Ticket Pro', 'active' => class_exists( 'WP_Multi_Ticket_Pro' ) ],
+ 'url_shop' => [ 'label' => '🛒 Shop-URL', 'plugin' => 'WP Ingame Shop Pro', 'active' => class_exists( 'WIS_Activator' ) ],
+ 'url_gallery' => [ 'label' => '📷 Galerie-URL', 'plugin' => 'MC MultiServer Gallery PRO', 'active' => post_type_exists( 'mc_gallery' ) ],
+ 'url_faq' => [ 'label' => '❓ FAQ-URL', 'plugin' => 'FAQ Post Type', 'active' => post_type_exists( 'faq' ) ],
+ 'url_player_history' => [ 'label' => '👤 Spieler-History-URL', 'plugin' => 'MC Player History', 'active' => function_exists( 'mcph_get_plugin_version' ) ],
+ 'url_forum' => [ 'label' => '💬 Forum-URL', 'plugin' => 'WP Business Forum', 'active' => class_exists( 'WBF_DB' ) ],
+ 'url_team' => [ 'label' => '👥 Team-URL', 'plugin' => '', 'active' => true ],
+ 'link_discord' => [ 'label' => '💬 Discord-Einladung', 'plugin' => '', 'active' => true ],
+ 'litebans_dashboard_url' => [ 'label' => '🔨 LiteBans Dashboard-URL', 'plugin' => 'LiteBans Manager', 'active' => class_exists( 'WP_LiteBans_Pro' ) ],
+ ];
+ ?>
+
+
+
+
+
+ ⚡ Alle erkannten URLs automatisch übernehmen
+
+
+
+
+
+
+
+
+
4. Individuelle Q&A
+
+ Schlüsselwörter (kommagetrennt) → Antwort. Hat höchste Priorität vor allen Plugin-Abfragen.
+
+
+
+
+ Neue Q&A-Zeile
+
+
+
+
+
+
+
+ '🖥️ Server-Status', 'q' => 'server status' ];
+ }
+
+ // Regeln – nur wenn URL im Backend gesetzt
+ if ( ! empty( $data['url_rules'] ) ) {
+ $quick[] = [ 'label' => '📜 Regelwerk', 'q' => 'regeln' ];
+ }
+
+ // Wiki – nur wenn URL im Backend gesetzt
+ if ( ! empty( $data['url_wiki'] ) ) {
+ $quick[] = [ 'label' => '📖 Wiki', 'q' => 'wiki' ];
+ }
+
+ // Shop – nur wenn URL im Backend gesetzt
+ global $wpdb;
+ if ( ! empty( $data['url_shop'] ) ) {
+ $quick[] = [ 'label' => '🛒 Shop', 'q' => 'shop' ];
+ }
+
+ // Ticket / Support – nur wenn URL im Backend gesetzt
+ if ( ! empty( $data['url_tickets'] ) ) {
+ $quick[] = [ 'label' => '🎫 Support-Ticket', 'q' => 'ticket erstellen' ];
+ }
+
+ // Forum
+ if ( class_exists( 'WBF_DB' ) && ! empty( $data['url_forum'] ) ) {
+ $quick[] = [ 'label' => '💬 Forum', 'q' => 'forum' ];
+ }
+
+ // Galerie – nur wenn URL im Backend gesetzt
+ if ( ! empty( $data['url_gallery'] ) ) {
+ $quick[] = [ 'label' => '📷 Galerie', 'q' => 'galerie' ];
+ }
+
+ // Ban-Status
+ $lb = get_option( 'wp_litebans_pro_settings', [] );
+ if ( ! empty( $lb['db_name'] ) ) {
+ $quick[] = [ 'label' => '🔨 Strafen prüfen', 'q' => 'meine strafen' ];
+ }
+
+ // Spieler-History – nur wenn URL im Backend gesetzt
+ if ( ! empty( $data['url_player_history'] ) ) {
+ $quick[] = [ 'label' => '⏱️ Spielzeit', 'q' => 'spielzeit' ];
+ }
+
+ // Discord
+ if ( ! empty( $data['link_discord'] ) ) {
+ $quick[] = [ 'label' => '💬 Discord', 'q' => 'discord' ];
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ➤
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_section( 'mm_bewerbung_section', array(
+ 'title' => __( 'Bewerbungsformular', 'minecraft-modern-theme' ),
+ 'priority' => 80,
+ ) );
+
+ $wp_customize->add_setting( 'mm_bewerbung_enabled', array(
+ 'default' => false,
+ 'sanitize_callback' => 'wp_validate_boolean',
+ ) );
+ $wp_customize->add_control( 'mm_bewerbung_enabled', array(
+ 'label' => __( 'Bewerbungsformular aktivieren', 'minecraft-modern-theme' ),
+ 'description' => __( 'Schaltet die Bewerbungsseite und das Formular ein.', 'minecraft-modern-theme' ),
+ 'section' => 'mm_bewerbung_section',
+ 'type' => 'checkbox',
+ ) );
+
+ $wp_customize->add_setting( 'mm_bewerbung_title', array(
+ 'default' => __( 'Bewirb dich bei uns!', 'minecraft-modern-theme' ),
+ 'sanitize_callback' => 'sanitize_text_field',
+ ) );
+ $wp_customize->add_control( 'mm_bewerbung_title', array(
+ 'label' => __( 'Titel der Bewerbungsseite', 'minecraft-modern-theme' ),
+ 'section' => 'mm_bewerbung_section',
+ 'type' => 'text',
+ ) );
+
+ $wp_customize->add_setting( 'mm_bewerbung_desc', array(
+ 'default' => __( 'Du möchtest Teil unseres Teams werden? Füll das Formular aus und wir melden uns bei dir.', 'minecraft-modern-theme' ),
+ 'sanitize_callback' => 'sanitize_textarea_field',
+ ) );
+ $wp_customize->add_control( 'mm_bewerbung_desc', array(
+ 'label' => __( 'Beschreibungstext', 'minecraft-modern-theme' ),
+ 'section' => 'mm_bewerbung_section',
+ 'type' => 'textarea',
+ ) );
+
+ $wp_customize->add_setting( 'mm_bewerbung_success_msg', array(
+ 'default' => __( 'Deine Bewerbung wurde erfolgreich eingereicht! Wir melden uns so bald wie möglich bei dir.', 'minecraft-modern-theme' ),
+ 'sanitize_callback' => 'sanitize_textarea_field',
+ ) );
+ $wp_customize->add_control( 'mm_bewerbung_success_msg', array(
+ 'label' => __( 'Erfolgsmeldung nach dem Absenden', 'minecraft-modern-theme' ),
+ 'section' => 'mm_bewerbung_section',
+ 'type' => 'textarea',
+ ) );
+
+ $wp_customize->add_setting( 'mm_bewerbung_min_alter', array(
+ 'default' => 14,
+ 'sanitize_callback' => 'absint',
+ ) );
+ $wp_customize->add_control( 'mm_bewerbung_min_alter', array(
+ 'label' => __( 'Mindestalter', 'minecraft-modern-theme' ),
+ 'description' => __( 'Bewerbungen unter diesem Alter werden abgelehnt. 0 = kein Limit.', 'minecraft-modern-theme' ),
+ 'section' => 'mm_bewerbung_section',
+ 'type' => 'number',
+ 'input_attrs' => array( 'min' => 0, 'max' => 99 ),
+ ) );
+
+ // ── Positionen ──
+ $wp_customize->add_setting( 'mm_bewerbung_positionen', array(
+ 'default' => "Moderator
+Supporter
+Builder
+Developer",
+ 'sanitize_callback' => 'sanitize_textarea_field',
+ ) );
+ $wp_customize->add_control( 'mm_bewerbung_positionen', array(
+ 'label' => __( 'Bewerbungs-Positionen', 'minecraft-modern-theme' ),
+ 'description' => __( 'Eine Position pro Zeile. Der Bewerber wählt genau eine davon aus.', 'minecraft-modern-theme' ),
+ 'section' => 'mm_bewerbung_section',
+ 'type' => 'textarea',
+ ) );
+}
+add_action( 'customize_register', 'mm_bewerbung_customizer' );
+
+// Hilfsfunktion: Positions-Liste als Array zurückgeben
+function mm_bewerbung_get_positionen() {
+ $raw = get_theme_mod( 'mm_bewerbung_positionen', "Moderator
+Supporter
+Builder
+Developer" );
+ $list = array_filter( array_map( 'trim', explode( "
+", $raw ) ) );
+ return array_values( $list );
+}
+
+
+// --- 2. Custom Post Type: Bewerbung ---
+function mm_register_bewerbung_cpt() {
+ if ( ! get_theme_mod( 'mm_bewerbung_enabled', false ) ) return;
+
+ register_post_type( 'mm_bewerbung', array(
+ 'labels' => array(
+ 'name' => __( 'Bewerbungen', 'minecraft-modern-theme' ),
+ 'singular_name' => __( 'Bewerbung', 'minecraft-modern-theme' ),
+ 'all_items' => __( 'Alle Bewerbungen', 'minecraft-modern-theme' ),
+ 'menu_name' => __( 'Bewerbungen', 'minecraft-modern-theme' ),
+ ),
+ 'public' => false,
+ 'show_ui' => true,
+ 'show_in_menu' => true,
+ 'menu_icon' => 'dashicons-clipboard',
+ 'menu_position' => 8,
+ 'supports' => array( 'title' ),
+ 'capabilities' => array(
+ 'create_posts' => 'do_not_allow', // Nur über Frontend erstellbar
+ ),
+ 'map_meta_cap' => true,
+ ) );
+}
+add_action( 'init', 'mm_register_bewerbung_cpt' );
+
+
+// --- 3. Admin: Meta-Box für Bewerbungs-Details ---
+function mm_bewerbung_meta_box() {
+ add_meta_box(
+ 'mm_bewerbung_details',
+ __( 'Bewerbungs-Details', 'minecraft-modern-theme' ),
+ 'mm_bewerbung_meta_box_html',
+ 'mm_bewerbung', 'normal', 'high'
+ );
+ add_meta_box(
+ 'mm_bewerbung_status_box',
+ __( 'Status', 'minecraft-modern-theme' ),
+ 'mm_bewerbung_status_box_html',
+ 'mm_bewerbung', 'side', 'high'
+ );
+}
+add_action( 'add_meta_boxes', 'mm_bewerbung_meta_box' );
+
+function mm_bewerbung_meta_box_html( $post ) {
+ $fields = array(
+ '_mm_bew_mc_name' => __( 'Minecraft Username', 'minecraft-modern-theme' ),
+ '_mm_bew_discord' => __( 'Discord Username', 'minecraft-modern-theme' ),
+ '_mm_bew_alter' => __( 'Alter', 'minecraft-modern-theme' ),
+ '_mm_bew_position' => __( 'Bewirbt sich als', 'minecraft-modern-theme' ),
+ '_mm_bew_warum' => __( 'Warum möchtest du mitspielen?', 'minecraft-modern-theme' ),
+ '_mm_bew_erfahrung' => __( 'Erfahrung / Vorstellung', 'minecraft-modern-theme' ),
+ '_mm_bew_datum' => __( 'Eingereicht am', 'minecraft-modern-theme' ),
+ '_mm_bew_ip' => __( 'IP-Adresse', 'minecraft-modern-theme' ),
+ );
+ echo '
';
+}
+
+function mm_bewerbung_status_box_html( $post ) {
+ $status = get_post_meta( $post->ID, '_mm_bew_status', true ) ?: 'neu';
+ wp_nonce_field( 'mm_bew_status_save', 'mm_bew_status_nonce' );
+ $options = array(
+ 'neu' => array( 'label' => __('Neu','minecraft-modern-theme'), 'color' => '#0073aa' ),
+ 'in_pruef' => array( 'label' => __('In Prüfung','minecraft-modern-theme'), 'color' => '#f0ad4e' ),
+ 'angenommen' => array( 'label' => __('Angenommen','minecraft-modern-theme'), 'color' => '#46b450' ),
+ 'abgelehnt' => array( 'label' => __('Abgelehnt','minecraft-modern-theme'), 'color' => '#dc3232' ),
+ );
+ echo '
';
+ foreach ( $options as $val => $opt ) {
+ $sel = selected( $status, $val, false );
+ echo '' . esc_html($opt['label']) . ' ';
+ }
+ echo ' ';
+ $cur = isset($options[$status]) ? $options[$status] : $options['neu'];
+ echo '
' . esc_html($cur['label']) . '
';
+
+ // Admin-Notiz
+ $notiz = get_post_meta( $post->ID, '_mm_bew_notiz', true );
+ echo '
';
+ echo '
' . __('Interne Notiz:', 'minecraft-modern-theme') . ' ';
+ echo '
' . esc_textarea($notiz) . ' ';
+}
+
+function mm_bewerbung_save_status( $post_id ) {
+ if ( ! isset($_POST['mm_bew_status_nonce']) || ! wp_verify_nonce($_POST['mm_bew_status_nonce'], 'mm_bew_status_save') ) return;
+ if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;
+ if ( ! current_user_can('edit_post', $post_id) ) return;
+ if ( isset($_POST['mm_bew_status']) ) {
+ update_post_meta( $post_id, '_mm_bew_status', sanitize_text_field($_POST['mm_bew_status']) );
+ }
+ if ( isset($_POST['mm_bew_notiz']) ) {
+ update_post_meta( $post_id, '_mm_bew_notiz', sanitize_textarea_field($_POST['mm_bew_notiz']) );
+ }
+}
+add_action( 'save_post', 'mm_bewerbung_save_status' );
+
+
+// --- 4. Admin-Spalten in der Bewerbungsliste ---
+function mm_bewerbung_columns( $cols ) {
+ return array(
+ 'cb' => $cols['cb'],
+ 'title' => __( 'Name', 'minecraft-modern-theme' ),
+ 'mc_name' => __( 'Minecraft', 'minecraft-modern-theme' ),
+ 'discord' => __( 'Discord', 'minecraft-modern-theme' ),
+ 'alter' => __( 'Alter', 'minecraft-modern-theme' ),
+ 'position' => __( 'Position', 'minecraft-modern-theme' ),
+ 'status' => __( 'Status', 'minecraft-modern-theme' ),
+ 'datum' => __( 'Eingereicht', 'minecraft-modern-theme' ),
+ );
+}
+add_filter( 'manage_mm_bewerbung_posts_columns', 'mm_bewerbung_columns' );
+
+function mm_bewerbung_column_content( $col, $post_id ) {
+ $status_colors = array(
+ 'neu' => '#0073aa',
+ 'in_pruef' => '#f0ad4e',
+ 'angenommen' => '#46b450',
+ 'abgelehnt' => '#dc3232',
+ );
+ $status_labels = array(
+ 'neu' => __('Neu','minecraft-modern-theme'),
+ 'in_pruef' => __('In Prüfung','minecraft-modern-theme'),
+ 'angenommen' => __('Angenommen','minecraft-modern-theme'),
+ 'abgelehnt' => __('Abgelehnt','minecraft-modern-theme'),
+ );
+ switch ($col) {
+ case 'mc_name':
+ $mc = get_post_meta($post_id, '_mm_bew_mc_name', true);
+ if ($mc) {
+ echo '
';
+ echo '
';
+ echo esc_html($mc) . '
';
+ }
+ break;
+ case 'discord':
+ echo esc_html( get_post_meta($post_id, '_mm_bew_discord', true) );
+ break;
+ case 'alter':
+ echo esc_html( get_post_meta($post_id, '_mm_bew_alter', true) );
+ break;
+ case 'position':
+ $pos = get_post_meta($post_id, '_mm_bew_position', true);
+ if ( $pos ) {
+ echo '
'
+ . esc_html($pos) . ' ';
+ } else {
+ echo '
— ';
+ }
+ break;
+ case 'status':
+ $s = get_post_meta($post_id, '_mm_bew_status', true) ?: 'neu';
+ $color = isset($status_colors[$s]) ? $status_colors[$s] : '#0073aa';
+ $label = isset($status_labels[$s]) ? $status_labels[$s] : $s;
+ echo '
' . esc_html($label) . ' ';
+ break;
+ case 'datum':
+ echo esc_html( get_post_meta($post_id, '_mm_bew_datum', true) );
+ break;
+ }
+}
+add_action( 'manage_mm_bewerbung_posts_custom_column', 'mm_bewerbung_column_content', 10, 2 );
+
+
+// --- 5. AJAX: Formular absenden ---
+add_action( 'wp_ajax_mm_submit_bewerbung', 'mm_submit_bewerbung' );
+add_action( 'wp_ajax_nopriv_mm_submit_bewerbung', 'mm_submit_bewerbung' );
+
+function mm_submit_bewerbung() {
+ // Nonce prüfen
+ if ( ! isset($_POST['nonce']) || ! wp_verify_nonce($_POST['nonce'], 'mm_bewerbung_nonce') ) {
+ wp_send_json_error( array('msg' => __('Sicherheitsfehler. Bitte Seite neu laden.', 'minecraft-modern-theme')) );
+ }
+
+ // Felder validieren
+ $mc_name = sanitize_text_field( $_POST['mc_name'] ?? '' );
+ $discord = sanitize_text_field( $_POST['discord'] ?? '' );
+ $alter_raw = absint( $_POST['alter'] ?? 0 );
+ $warum = sanitize_textarea_field( $_POST['warum'] ?? '' );
+ $erfahrung = sanitize_textarea_field( $_POST['erfahrung'] ?? '' );
+
+ $position = sanitize_text_field( $_POST['position'] ?? '' );
+ $positionen = mm_bewerbung_get_positionen();
+
+ $errors = array();
+ if ( empty($mc_name) ) $errors[] = __('Minecraft Username ist erforderlich.', 'minecraft-modern-theme');
+ if ( empty($discord) ) $errors[] = __('Discord Username ist erforderlich.', 'minecraft-modern-theme');
+ if ( $alter_raw < 1 ) $errors[] = __('Bitte gib dein Alter an.', 'minecraft-modern-theme');
+ if ( ! empty($positionen) && ! in_array($position, $positionen, true) ) {
+ $errors[] = __('Bitte wähle eine gültige Position aus.', 'minecraft-modern-theme');
+ }
+ if ( empty($warum) ) $errors[] = __('Bitte erkläre warum du mitspielen möchtest.', 'minecraft-modern-theme');
+ if ( empty($erfahrung) ) $errors[] = __('Bitte stell dich kurz vor.', 'minecraft-modern-theme');
+
+ // Mindestalter prüfen
+ $min_alter = absint( get_theme_mod('mm_bewerbung_min_alter', 14) );
+ if ( $min_alter > 0 && $alter_raw < $min_alter ) {
+ $errors[] = sprintf( __('Du musst mindestens %d Jahre alt sein.', 'minecraft-modern-theme'), $min_alter );
+ }
+
+ // Doppelbewerbung prüfen (gleicher MC-Name in den letzten 30 Tagen)
+ $existing = get_posts( array(
+ 'post_type' => 'mm_bewerbung',
+ 'post_status' => 'publish',
+ 'meta_query' => array(
+ array( 'key' => '_mm_bew_mc_name', 'value' => $mc_name, 'compare' => '=' ),
+ ),
+ 'date_query' => array(
+ array( 'after' => '30 days ago' ),
+ ),
+ 'numberposts' => 1,
+ ) );
+ if ( $existing ) {
+ $errors[] = __('Mit diesem Minecraft-Namen wurde in den letzten 30 Tagen bereits eine Bewerbung eingereicht.', 'minecraft-modern-theme');
+ }
+
+ if ( ! empty($errors) ) {
+ wp_send_json_error( array('msg' => implode(' ', $errors)) );
+ }
+
+ // Bewerbung als Post speichern
+ $post_id = wp_insert_post( array(
+ 'post_type' => 'mm_bewerbung',
+ 'post_status' => 'publish',
+ 'post_title' => $mc_name . ' – ' . date_i18n('d.m.Y H:i'),
+ ) );
+
+ if ( is_wp_error($post_id) ) {
+ wp_send_json_error( array('msg' => __('Fehler beim Speichern. Bitte versuche es erneut.', 'minecraft-modern-theme')) );
+ }
+
+ update_post_meta( $post_id, '_mm_bew_mc_name', $mc_name );
+ update_post_meta( $post_id, '_mm_bew_discord', $discord );
+ update_post_meta( $post_id, '_mm_bew_alter', $alter_raw );
+ update_post_meta( $post_id, '_mm_bew_position', $position );
+ update_post_meta( $post_id, '_mm_bew_warum', $warum );
+ update_post_meta( $post_id, '_mm_bew_erfahrung', $erfahrung );
+ update_post_meta( $post_id, '_mm_bew_status', 'neu' );
+ update_post_meta( $post_id, '_mm_bew_datum', date_i18n('d.m.Y H:i:s') );
+ update_post_meta( $post_id, '_mm_bew_ip', sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '' ) );
+
+ $success_msg = get_theme_mod( 'mm_bewerbung_success_msg', __('Deine Bewerbung wurde erfolgreich eingereicht! Wir melden uns so bald wie möglich bei dir.', 'minecraft-modern-theme') );
+ wp_send_json_success( array('msg' => $success_msg) );
+}
+
+
+// --- 6. Template-Loader ---
+function mm_bewerbung_template_loader( $template ) {
+ if ( ! get_theme_mod('mm_bewerbung_enabled', false) ) return $template;
+ if ( is_page('bewerbung') ) {
+ // BUG-FIX: locate_template() statt get_template_directory(),
+ // damit ein page-bewerbung.php im Child-Theme greift.
+ $t = locate_template( 'page-bewerbung.php' );
+ if ( $t ) return $t;
+ }
+ return $template;
+}
+add_filter( 'template_include', 'mm_bewerbung_template_loader' );
+
+
+// --- 7. Seite automatisch anlegen ---
+function mm_bewerbung_create_page() {
+ if ( ! get_theme_mod('mm_bewerbung_enabled', false) ) return;
+ if ( ! get_page_by_path('bewerbung') ) {
+ wp_insert_post( array(
+ 'post_title' => __('Bewerbung', 'minecraft-modern-theme'),
+ 'post_name' => 'bewerbung',
+ 'post_status' => 'publish',
+ 'post_type' => 'page',
+ 'post_author' => 1,
+ ) );
+ }
+}
+add_action( 'customize_save_after', 'mm_bewerbung_create_page' );
diff --git a/Minecraft-Modern-Theme/inc/cookie-banner.php b/Minecraft-Modern-Theme/inc/cookie-banner.php
new file mode 100644
index 0000000..774cc72
--- /dev/null
+++ b/Minecraft-Modern-Theme/inc/cookie-banner.php
@@ -0,0 +1,283 @@
+
+
+ add_section( 'mm_cookie_banner_section', array(
+ 'title' => __( 'Cookie-Banner (DSGVO)', 'minecraft-modern-theme' ),
+ 'priority' => 75,
+ ) );
+
+ $wp_customize->add_setting( 'mm_cookie_enabled', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean', 'transport' => 'postMessage' ) );
+ $wp_customize->add_control( 'mm_cookie_enabled', array( 'label' => __( 'Cookie-Banner aktivieren', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'checkbox' ) );
+
+ $wp_customize->add_setting( 'mm_cookie_style', array( 'default' => 'bar', 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'postMessage' ) );
+ $wp_customize->add_control( 'mm_cookie_style', array(
+ 'label' => __( 'Design-Variante', 'minecraft-modern-theme' ),
+ 'section' => 'mm_cookie_banner_section',
+ 'type' => 'select',
+ 'choices' => array(
+ 'bar' => __( 'Variante 1 – Schmale Bar (volle Breite)', 'minecraft-modern-theme' ),
+ 'split' => __( 'Variante 2 – Zweispaltig (3A)', 'minecraft-modern-theme' ),
+ 'slide' => __( 'Variante 3 – Slide-In von rechts (3B)', 'minecraft-modern-theme' ),
+ 'stepper' => __( 'Variante 4 – Kompakt-Center mit Stepper (3C)', 'minecraft-modern-theme' ),
+ ),
+ ) );
+
+ $wp_customize->add_setting( 'mm_cookie_text', array( 'default' => __( 'Wir nutzen Cookies und ähnliche Technologien. Einige sind essenziell, andere helfen uns diese Website zu verbessern. Du kannst deine Auswahl jederzeit anpassen.', 'minecraft-modern-theme' ), 'sanitize_callback' => 'wp_kses_post', 'transport' => 'postMessage' ) );
+ $wp_customize->add_control( 'mm_cookie_text', array( 'label' => __( 'Banner-Text', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'textarea' ) );
+
+ $wp_customize->add_setting( 'mm_cookie_privacy_url', array( 'default' => '', 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( 'mm_cookie_privacy_url', array( 'label' => __( 'URL Datenschutzerklärung', 'minecraft-modern-theme' ), 'description' => __( 'Leer lassen um den Link auszublenden.', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'url' ) );
+
+ foreach ( array(
+ 'necessary' => array( 'label' => __( 'Beschreibung: Notwendige', 'minecraft-modern-theme' ), 'default' => __( 'Grundlegende Funktionen der Website. Können nicht deaktiviert werden.', 'minecraft-modern-theme' ) ),
+ 'statistics' => array( 'label' => __( 'Beschreibung: Statistik', 'minecraft-modern-theme' ), 'default' => __( 'Helfen uns zu verstehen wie Besucher mit der Website interagieren (z.B. Google Analytics).', 'minecraft-modern-theme' ) ),
+ 'marketing' => array( 'label' => __( 'Beschreibung: Marketing', 'minecraft-modern-theme' ), 'default' => __( 'Werden genutzt um Werbung relevanter zu gestalten (z.B. YouTube, Facebook).', 'minecraft-modern-theme' ) ),
+ ) as $key => $opts ) {
+ $wp_customize->add_setting( 'mm_cookie_desc_' . $key, array( 'default' => $opts['default'], 'sanitize_callback' => 'sanitize_textarea_field' ) );
+ $wp_customize->add_control( 'mm_cookie_desc_' . $key, array( 'label' => $opts['label'], 'section' => 'mm_cookie_banner_section', 'type' => 'textarea' ) );
+ }
+
+ $wp_customize->add_setting( 'mm_cookie_ga_id', array( 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'mm_cookie_ga_id', array( 'label' => __( 'Google Analytics ID (optional)', 'minecraft-modern-theme' ), 'description' => __( 'z.B. G-XXXXXXXXXX', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'text' ) );
+
+ $wp_customize->add_setting( 'mm_cookie_lifetime', array( 'default' => 365, 'sanitize_callback' => 'absint' ) );
+ $wp_customize->add_control( 'mm_cookie_lifetime', array( 'label' => __( 'Cookie-Laufzeit (Tage)', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'number', 'input_attrs' => array( 'min' => 1, 'max' => 730 ) ) );
+
+ if ( class_exists( 'MM_Cookie_Preview_Control' ) ) {
+ $wp_customize->add_setting( 'mm_cookie_preview_dummy', array( 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( new MM_Cookie_Preview_Control( $wp_customize, 'mm_cookie_preview_dummy', array( 'section' => 'mm_cookie_banner_section', 'priority' => 200 ) ) );
+ }
+}
+add_action( 'customize_register', 'mm_cookie_banner_customizer' );
+
+
+// --- 2. Banner HTML – ALLE 4 LAYOUTS gleichzeitig ausgeben ---
+// Im Customizer wechselt JS nur die Klasse auf #mm-cookie-banner.
+// CSS zeigt immer nur das passende .mmc-layout-* div.
+function mm_cookie_banner_render() {
+ $is_preview = is_customize_preview();
+ if ( ! $is_preview && ! get_theme_mod( 'mm_cookie_enabled', true ) ) return;
+
+ $style = get_theme_mod( 'mm_cookie_style', 'bar' );
+ $text = get_theme_mod( 'mm_cookie_text', __( 'Wir nutzen Cookies und ähnliche Technologien. Einige sind essenziell, andere helfen uns diese Website zu verbessern.', 'minecraft-modern-theme' ) );
+ $priv_url = get_theme_mod( 'mm_cookie_privacy_url', '' );
+ $lifetime = absint( get_theme_mod( 'mm_cookie_lifetime', 365 ) );
+ $ga_id = get_theme_mod( 'mm_cookie_ga_id', '' );
+ $desc_n = get_theme_mod( 'mm_cookie_desc_necessary', __( 'Grundlegende Funktionen der Website. Können nicht deaktiviert werden.', 'minecraft-modern-theme' ) );
+ $desc_s = get_theme_mod( 'mm_cookie_desc_statistics', __( 'Helfen uns zu verstehen wie Besucher mit der Website interagieren (z.B. Google Analytics).', 'minecraft-modern-theme' ) );
+ $desc_m = get_theme_mod( 'mm_cookie_desc_marketing', __( 'Werden genutzt um Werbung relevanter zu gestalten (z.B. YouTube, Facebook).', 'minecraft-modern-theme' ) );
+
+ $priv_link = $priv_url ? '
' . __( 'Datenschutzerklärung', 'minecraft-modern-theme' ) . ' ' : '';
+ $preview_class = $is_preview ? ' mmc-visible mmc-preview-mode' : '';
+ $inline_style = $is_preview ? '' : 'display:none;';
+
+ // Kategorien-Block (identisch in allen Varianten mit Kategorien)
+ $cats = '
+
' . __('Notwendige','minecraft-modern-theme') . '' . __('Immer aktiv','minecraft-modern-theme') . '
' . esc_html($desc_n) . '
+
+
+
';
+
+ $btn_accept = '
' . __('Alle akzeptieren','minecraft-modern-theme') . '';
+ $btn_select = '
' . __('Auswahl speichern','minecraft-modern-theme') . '';
+ $btn_neces = '
' . __('Nur notwendige','minecraft-modern-theme') . ' ';
+
+ $text_esc = wp_kses_post($text);
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ' . $priv_link . ''; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __('Cookie-Einstellungen','minecraft-modern-theme')),$atts);return '
'.esc_html($a['text']).' ';}
+add_shortcode('cookie_settings','mm_cookie_settings_shortcode');
+
+
+// --- 4. Live-Vorschau: nur Klasse + Text wechseln, HTML ist bereits vollständig ---
+function mm_cookie_banner_preview_js(){
+ if(!is_customize_preview())return; ?>
+
+ direkt in wp_head
- * - slider_loop Setting ergänzt (war in slider-init.js referenziert, aber nie definiert)
- * - Scroll-to-Top Toggle ergänzt
- * - footer_copyright Default mit aktuellem Jahr zur Laufzeit
- * - Import_Export_Control Klasse aus dem Callback extrahiert
- */
-
-// =========================================================================
-// Import/Export Control – außerhalb des Callbacks definiert
-// =========================================================================
-if ( class_exists('WP_Customize_Control') && ! class_exists('MM_Import_Export_Control') ) :
-class MM_Import_Export_Control extends WP_Customize_Control {
- public $type = 'mm_import_export';
-
- public function render_content() {
- $export_url = admin_url('admin-post.php?action=export_theme_settings');
- $nonce = wp_create_nonce('theme-import-nonce');
- ?>
-
-
-
-
-
-
-
- 📦 Was wird gesichert:
- ✓ Customizer-Einstellungen (Farben, Social Links, Menü-Design, etc.)
- ✓ Livestream API Keys (YouTube, Twitch)
- ✓ Homepage-Seite (Titel, Inhalt, Highlight-Bild)
- ✓ Navigation Menüs inkl. aller Items & Struktur
- ✓ Widget-Konfigurationen
- ✓ Team-Mitglieder (mit UUID, Avatar, Banner)
- ✓ FAQ-Einträge & Kategorien
- ✓ Custom CSS
- ✓ Announcement-Bar Einstellungen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ⚠️
-
-
-
-
- add_section( 'assistant_settings', array(
- 'title' => __( 'Virtueller Assistent', 'minecraft-modern-theme' ),
- 'priority' => 80,
- 'description' => __( 'Steuert den virtuellen Assistenten im Frontend. Avatar basiert auf Minecraft-UUID.', 'minecraft-modern-theme' ),
- ) );
-
- $wp_customize->add_setting( 'assistant_enabled', array(
- 'default' => false,
- 'sanitize_callback' => 'wp_validate_boolean',
- ) );
- $wp_customize->add_control( 'assistant_enabled', array(
- 'label' => __( 'Virtuellen Assistenten aktivieren', 'minecraft-modern-theme' ),
- 'section' => 'assistant_settings',
- 'type' => 'checkbox',
- ) );
-
- $wp_customize->add_setting( 'assistant_minecraft_uuid', array(
- 'default' => '',
- 'sanitize_callback' => 'sanitize_text_field',
- ) );
- $wp_customize->add_control( 'assistant_minecraft_uuid', array(
- 'label' => __( 'Minecraft UUID für Avatar', 'minecraft-modern-theme' ),
- 'section' => 'assistant_settings',
- 'type' => 'text',
- 'description' => __( 'Gib die Minecraft-UUID für den Avatar des Assistenten ein.', 'minecraft-modern-theme' ),
- ) );
-
- $wp_customize->add_setting( 'assistant_avatar_view', array(
- 'default' => 'head',
- 'sanitize_callback' => function ( $v ) {
- return in_array( $v, array( 'head', 'body', '3dhead' ), true ) ? $v : 'head';
- },
- ) );
- $wp_customize->add_control( 'assistant_avatar_view', array(
- 'label' => __( 'Avatar-Ansicht', 'minecraft-modern-theme' ),
- 'section' => 'assistant_settings',
- 'type' => 'select',
- 'choices' => array(
- 'head' => __( 'Kopf', 'minecraft-modern-theme' ),
- 'body' => __( 'Ganzkörper', 'minecraft-modern-theme' ),
- '3dhead' => __( '3D Kopf', 'minecraft-modern-theme' ),
- ),
- 'description' => __( 'Wähle, wie der Minecraft-Avatar im Assistenten angezeigt wird.', 'minecraft-modern-theme' ),
- ) );
-
- // BUG-FIX: assistant_position war in assistant-widget.php in einem eigenen
- // customize_register-Hook registriert – also BEVOR diese Section existierte.
- // Jetzt korrekt hier innerhalb von minecraft_modern_customize_register().
- $wp_customize->add_setting( 'assistant_position', array(
- 'default' => 'bottom_right',
- 'transport' => 'refresh',
- 'sanitize_callback' => function ( $v ) {
- $allowed = array( 'bottom_right', 'bottom_left', 'top_right', 'top_left' );
- return in_array( $v, $allowed, true ) ? $v : 'bottom_right';
- },
- ) );
- $wp_customize->add_control( 'assistant_position', array(
- 'label' => __( 'Position des Assistenten', 'minecraft-modern-theme' ),
- 'section' => 'assistant_settings',
- 'type' => 'select',
- 'choices' => array(
- 'bottom_right' => __( 'Unten rechts', 'minecraft-modern-theme' ),
- 'bottom_left' => __( 'Unten links', 'minecraft-modern-theme' ),
- 'top_right' => __( 'Oben rechts', 'minecraft-modern-theme' ),
- 'top_left' => __( 'Oben links', 'minecraft-modern-theme' ),
- ),
- ) );
-
- // =========================================================================
- // 1. HEADER SLIDER
- // =========================================================================
- $wp_customize->add_section( 'header_slider', array(
- 'title' => __('Header Slider', 'minecraft-modern-theme'),
- 'priority' => 20,
- 'description' => __('Konfiguriere den großen Slider auf der Startseite.', 'minecraft-modern-theme'),
- ) );
-
- $wp_customize->add_setting( 'slider_enabled', array( 'default' => false, 'transport' => 'refresh', 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'slider_enabled', array( 'label' => __('Header Slider aktivieren', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'checkbox' ) );
-
- // FIX: slider_loop war in slider-init.js als sliderSettings.loop referenziert, aber nie definiert
- $wp_customize->add_setting( 'slider_loop', array( 'default' => true, 'transport' => 'refresh', 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'slider_loop', array(
- 'label' => __('Slider Endlos-Loop aktivieren', 'minecraft-modern-theme'),
- 'description' => __('Der Slider springt nach dem letzten Slide wieder zum ersten zurück.', 'minecraft-modern-theme'),
- 'section' => 'header_slider',
- 'type' => 'checkbox',
- ) );
-
- for ( $i = 1; $i <= 5; $i++ ) {
- $wp_customize->add_setting( 'slider_image_' . $i, array( 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'slider_image_' . $i, array(
- 'label' => sprintf( __('Banner %d - Bild', 'minecraft-modern-theme'), $i ), 'section' => 'header_slider',
- ) ) );
- $wp_customize->add_setting( 'slider_title_' . $i, array( 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'slider_title_' . $i, array( 'label' => sprintf( __('Banner %d - Titel', 'minecraft-modern-theme'), $i ), 'section' => 'header_slider', 'type' => 'text' ) );
- $wp_customize->add_setting( 'slider_subtitle_' . $i, array( 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'slider_subtitle_' . $i, array( 'label' => sprintf( __('Banner %d - Untertitel', 'minecraft-modern-theme'), $i ), 'section' => 'header_slider', 'type' => 'text' ) );
- }
-
- $wp_customize->add_setting( 'slider_font_family', array( 'default' => 'Raleway', 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'slider_font_family', array(
- 'label' => __('Schriftart', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'select',
- 'choices' => array( 'Raleway' => 'Raleway', 'Poppins' => 'Poppins', 'Montserrat' => 'Montserrat', 'Oswald' => 'Oswald', 'Roboto' => 'Roboto', 'Lato' => 'Lato' ),
- ) );
-
- $wp_customize->add_setting( 'slider_font_size', array( 'default' => 'mittel', 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'slider_font_size', array(
- 'label' => __('Schriftgröße', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'select',
- 'choices' => array( 'klein' => __('Klein', 'minecraft-modern-theme'), 'mittel' => __('Mittel', 'minecraft-modern-theme'), 'gross' => __('Groß', 'minecraft-modern-theme'), 'extra-gross' => __('Extra Groß', 'minecraft-modern-theme') ),
- ) );
-
- $wp_customize->add_setting( 'slider_font_color', array( 'default' => '#ffffff', 'sanitize_callback' => 'sanitize_hex_color' ) );
- $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'slider_font_color', array(
- 'label' => __('Schriftfarbe', 'minecraft-modern-theme'), 'section' => 'header_slider',
- ) ) );
-
- $wp_customize->add_setting( 'header_height', array( 'default' => 'mittel', 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'header_height', array(
- 'label' => __('Header-Höhe', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'select',
- 'choices' => array( 'klein' => __('Klein', 'minecraft-modern-theme'), 'mittel' => __('Mittel', 'minecraft-modern-theme'), 'gross' => __('Groß', 'minecraft-modern-theme') ),
- ) );
-
- $wp_customize->add_setting( 'slider_hide_arrows', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'slider_hide_arrows', array( 'label' => __('Pfeile ausblenden', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'checkbox' ) );
-
- $wp_customize->add_setting( 'slider_hide_pagination', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'slider_hide_pagination', array( 'label' => __('Paginierung (Punkte) ausblenden', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'checkbox' ) );
-
-
- // =========================================================================
- // 2. HERO SECTION (Fallback)
- // =========================================================================
- $wp_customize->add_section( 'hero_section', array(
- 'title' => __('Startseiten-Hero (wenn Slider deaktiviert)', 'minecraft-modern-theme'),
- 'priority' => 21,
- ) );
-
- $wp_customize->add_setting( 'hero_title', array( 'default' => __('Willkommen auf unserem Server', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'hero_title', array( 'label' => __('Haupttitel', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
- $wp_customize->add_setting( 'hero_subtitle', array( 'default' => __('Trete einer Community voller Abenteuer bei.', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'hero_subtitle', array( 'label' => __('Untertitel', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
- $wp_customize->add_setting( 'hero_bg_image', array( 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'hero_bg_image', array( 'label' => __('Hintergrundbild', 'minecraft-modern-theme'), 'section' => 'hero_section' ) ) );
- $wp_customize->add_setting( 'hero_button_1_text', array( 'default' => __('Zum Forum', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'hero_button_1_text', array( 'label' => __('Button 1 Text', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
- $wp_customize->add_setting( 'hero_button_1_url', array( 'default' => '#', 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( 'hero_button_1_url', array( 'label' => __('Button 1 URL', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'url' ) );
- $wp_customize->add_setting( 'hero_button_2_text', array( 'default' => __('Zum Teamspeak', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( 'hero_button_2_text', array( 'label' => __('Button 2 Text', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
- $wp_customize->add_setting( 'hero_button_2_url', array( 'default' => '#', 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( 'hero_button_2_url', array( 'label' => __('Button 2 URL', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'url' ) );
- $wp_customize->add_setting( 'show_home_title', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'show_home_title', array( 'label' => __('Seitentitel "Home" anzeigen', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'checkbox' ) );
-
-
- // =========================================================================
- // 3. FARBEN & DARSTELLUNG
- // =========================================================================
- $wp_customize->add_section( 'theme_appearance_settings', array(
- 'title' => __('Farben & Darstellung', 'minecraft-modern-theme'), 'priority' => 30,
- ) );
-
- $wp_customize->add_setting( 'theme_color_preset', array( 'default' => 'classic', 'sanitize_callback' => 'sanitize_key', 'transport' => 'refresh' ) );
- $wp_customize->add_control( 'theme_color_preset', array(
- 'label' => __('Theme Preset (Farbschema)', 'minecraft-modern-theme'),
- 'section' => 'theme_appearance_settings',
- 'type' => 'select',
- 'priority' => 1,
- 'choices' => array(
- 'classic' => __('Classic Minecraft (Diamant-Blau)', 'minecraft-modern-theme'),
- 'nether' => __('Nether (Lava-Rot)', 'minecraft-modern-theme'),
- 'end' => __('The End (Ender-Purpur)', 'minecraft-modern-theme'),
- ),
- ) );
-
- $wp_customize->add_setting( 'primary_accent_color', array( 'default' => '#00d4ff', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'refresh' ) );
- $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'primary_accent_color', array( 'label' => __('Akzentfarbe', 'minecraft-modern-theme'), 'section' => 'theme_appearance_settings' ) ) );
-
- $wp_customize->add_setting( 'default_theme_mode', array( 'default' => 'dark', 'sanitize_callback' => 'sanitize_key' ) );
- $wp_customize->add_control( 'default_theme_mode', array(
- 'label' => __('Standard-Theme-Modus', 'minecraft-modern-theme'),
- 'section' => 'theme_appearance_settings',
- 'type' => 'radio',
- 'choices' => array( 'dark' => __('Dark Mode', 'minecraft-modern-theme'), 'light' => __('Light Mode', 'minecraft-modern-theme') ),
- ) );
-
- // FIX: Scroll-to-Top war nie im Customizer steuerbar
- $wp_customize->add_setting( 'show_scroll_to_top', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'show_scroll_to_top', array(
- 'label' => __('Scroll-to-Top Button anzeigen', 'minecraft-modern-theme'),
- 'description' => __('Zeigt einen Button unten rechts zum Hochscrollen an.', 'minecraft-modern-theme'),
- 'section' => 'theme_appearance_settings',
- 'type' => 'checkbox',
- ) );
-
-
- // =========================================================================
- // 4. SIDEBAR
- // =========================================================================
- $wp_customize->add_section( 'sidebar_settings', array( 'title' => __('Sidebar Einstellungen', 'minecraft-modern-theme'), 'priority' => 35 ) );
- $wp_customize->add_setting( 'homepage_sidebar_enabled', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'homepage_sidebar_enabled', array( 'label' => __('Sidebar auf Startseite aktivieren', 'minecraft-modern-theme'), 'section' => 'sidebar_settings', 'type' => 'checkbox' ) );
- $wp_customize->add_setting( 'homepage_sidebar_position', array( 'default' => 'right', 'sanitize_callback' => 'sanitize_key' ) );
- $wp_customize->add_control( 'homepage_sidebar_position', array(
- 'label' => __('Sidebar Position', 'minecraft-modern-theme'), 'section' => 'sidebar_settings', 'type' => 'select',
- 'choices' => array( 'left' => __('Links', 'minecraft-modern-theme'), 'right' => __('Rechts', 'minecraft-modern-theme') ),
- ) );
-
-
- // =========================================================================
- // 5. SOCIAL MEDIA
- // =========================================================================
- $wp_customize->add_section( 'social_links', array( 'title' => __('Social Media Links', 'minecraft-modern-theme'), 'priority' => 40 ) );
- $social_platforms = array(
- 'bluesky' => 'BlueSky', 'discord' => 'Discord', 'youtube' => 'YouTube', 'twitter' => 'Twitter (X)',
- 'facebook' => 'Facebook', 'instagram' => 'Instagram', 'tiktok' => 'TikTok',
- 'twitch' => 'Twitch', 'steam' => 'Steam', 'github' => 'GitHub',
- 'linkedin' => 'LinkedIn', 'pinterest' => 'Pinterest', 'reddit' => 'Reddit',
- 'mastodon' => 'Mastodon', 'threads' => 'Threads', 'kickstarter' => 'Kickstarter',
- 'teamspeak' => 'Teamspeak', 'spotify' => 'Spotify', 'stoat' => 'Stoat',
- );
- foreach ( $social_platforms as $key => $label ) {
- $wp_customize->add_setting( 'social_' . $key, array( 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( 'social_' . $key, array( 'label' => $label . ' URL', 'section' => 'social_links', 'type' => 'url' ) );
- }
-
- // =========================================================================
- // 6. FOOTER
- // =========================================================================
- $wp_customize->add_section( 'footer_settings', array( 'title' => __('Footer-Einstellungen', 'minecraft-modern-theme'), 'priority' => 50 ) );
-
- // FIX: Default mit aktuellem Jahr zur Laufzeit auswerten, nicht bei class-load
- $wp_customize->add_setting( 'footer_copyright', array(
- 'default' => '', // Leer = dynamisch berechnet in footer.php
- 'sanitize_callback' => 'wp_kses_post',
- ) );
- $wp_customize->add_control( 'footer_copyright', array(
- 'label' => __('Copyright-Text', 'minecraft-modern-theme'),
- 'description' => __('Leer lassen für automatischen Text mit aktuellem Jahr.', 'minecraft-modern-theme'),
- 'section' => 'footer_settings',
- 'type' => 'textarea',
- ) );
-
- $wp_customize->add_setting( 'footer_impressum_url', array( 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( 'footer_impressum_url', array( 'label' => __('URL für Impressum', 'minecraft-modern-theme'), 'section' => 'footer_settings', 'type' => 'url' ) );
- $wp_customize->add_setting( 'footer_datenschutz_url', array( 'sanitize_callback' => 'esc_url_raw' ) );
- $wp_customize->add_control( 'footer_datenschutz_url', array( 'label' => __('URL für Datenschutz', 'minecraft-modern-theme'), 'section' => 'footer_settings', 'type' => 'url' ) );
- $wp_customize->add_setting( 'show_footer_credit', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'show_footer_credit', array( 'label' => __('Footer-Credit anzeigen', 'minecraft-modern-theme'), 'section' => 'footer_settings', 'type' => 'checkbox' ) );
-
-
- // =========================================================================
- // 7. FAQ & TEAM
- // =========================================================================
- $wp_customize->add_section( 'faq_settings', array( 'title' => __('FAQ Einstellungen', 'minecraft-modern-theme'), 'priority' => 60 ) );
- $wp_customize->add_setting( 'faq_enabled', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'faq_enabled', array( 'label' => __('FAQ System aktivieren', 'minecraft-modern-theme'), 'section' => 'faq_settings', 'type' => 'checkbox' ) );
-
- $wp_customize->add_section( 'team_settings', array( 'title' => __('Team Einstellungen', 'minecraft-modern-theme'), 'priority' => 65 ) );
- $wp_customize->add_setting( 'team_enabled', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
- $wp_customize->add_control( 'team_enabled', array( 'label' => __('Team Showcase aktivieren', 'minecraft-modern-theme'), 'section' => 'team_settings', 'type' => 'checkbox' ) );
-
-
- // =========================================================================
- // 8. LOGIN
- // =========================================================================
- $wp_customize->add_section( 'login_settings', array( 'title' => __('Login-Einstellungen', 'minecraft-modern-theme'), 'priority' => 70 ) );
- $wp_customize->add_setting( 'login_background_image', array( 'sanitize_callback' => 'esc_url_raw', 'transport' => 'refresh' ) );
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'login_background_image', array( 'label' => __('Login-Hintergrundbild', 'minecraft-modern-theme'), 'section' => 'login_settings' ) ) );
- $wp_customize->add_setting( 'login_logo', array( 'sanitize_callback' => 'esc_url_raw', 'transport' => 'refresh' ) );
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'login_logo', array( 'label' => __('Login-Logo', 'minecraft-modern-theme'), 'section' => 'login_settings' ) ) );
-
- for ( $i = 1; $i <= 5; $i++ ) {
- $wp_customize->add_setting( 'login_avatar_uuid_' . $i, array( 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'refresh' ) );
- $wp_customize->add_control( 'login_avatar_uuid_' . $i, array(
- 'label' => sprintf( __('Avatar %d UUID', 'minecraft-modern-theme'), $i ),
- 'section' => 'login_settings',
- 'type' => 'text',
- ) );
- }
-
- $wp_customize->add_setting( 'login_avatar_slider_speed', array( 'default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'refresh' ) );
- $wp_customize->add_control( 'login_avatar_slider_speed', array(
- 'label' => __('Avatar-Wechsel (Sekunden)', 'minecraft-modern-theme'),
- 'section' => 'login_settings',
- 'type' => 'number',
- 'input_attrs' => array( 'min' => 2, 'max' => 10, 'step' => 1 ),
- ) );
-
-
- // =========================================================================
- // 8.5. VIDEO / LIVESTREAM EINSTELLUNGEN
- // =========================================================================
- $wp_customize->add_section( 'video_livestream_settings', array(
- 'title' => __('Video & Livestream', 'minecraft-modern-theme'),
- 'description' => __('Einstellungen für YouTube Livestream-Erkennung. Hauptmethode: Livestream-Posts unter "Livestreams" erstellen. Optional: Zusätzlichen Hauptkanal hier eintragen.', 'minecraft-modern-theme'),
- 'priority' => 75,
- ) );
-
- $wp_customize->add_setting( 'youtube_api_key', array(
- 'default' => '',
- 'sanitize_callback' => 'sanitize_text_field',
- 'transport' => 'refresh',
- ) );
- $wp_customize->add_control( 'youtube_api_key', array(
- 'label' => __('YouTube API Key', 'minecraft-modern-theme'),
- 'description' => __('Erforderlich für automatische YouTube Live-Erkennung.
Hier API Key erstellen ', 'minecraft-modern-theme'),
- 'section' => 'video_livestream_settings',
- 'type' => 'text',
- 'input_attrs' => array(
- 'placeholder' => 'AIzaSyD...',
- ),
- ) );
-
- $wp_customize->add_setting( 'twitch_client_id', array(
- 'default' => '',
- 'sanitize_callback' => 'sanitize_text_field',
- 'transport' => 'refresh',
- ) );
- $wp_customize->add_control( 'twitch_client_id', array(
- 'label' => __('Twitch Client ID', 'minecraft-modern-theme'),
- 'description' => __('Erforderlich für Twitch Live-Erkennung.
Hier App erstellen ', 'minecraft-modern-theme'),
- 'section' => 'video_livestream_settings',
- 'type' => 'text',
- 'input_attrs' => array(
- 'placeholder' => 'xxxxxxxxxxxxxx',
- ),
- ) );
-
- $wp_customize->add_setting( 'twitch_client_secret', array(
- 'default' => '',
- 'sanitize_callback' => 'sanitize_text_field',
- 'transport' => 'refresh',
- ) );
- $wp_customize->add_control( 'twitch_client_secret', array(
- 'label' => __('Twitch Client Secret', 'minecraft-modern-theme'),
- 'description' => __('Nur für Live-Prüfung. Wird serverseitig genutzt.', 'minecraft-modern-theme'),
- 'section' => 'video_livestream_settings',
- 'type' => 'text',
- 'input_attrs' => array(
- 'placeholder' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
- ),
- ) );
-
- // =========================================================================
- // 9. EXPORT / IMPORT
- // =========================================================================
- $wp_customize->add_section( 'theme_mods_import_export', array(
- 'title' => __('Einstellungen sichern', 'minecraft-modern-theme'),
- 'priority' => 999,
- ) );
- $wp_customize->add_setting( 'import_export_placeholder', array( 'sanitize_callback' => 'sanitize_text_field' ) );
- $wp_customize->add_control( new MM_Import_Export_Control( $wp_customize, 'import_export_placeholder', array(
- 'section' => 'theme_mods_import_export',
- ) ) );
-}
-add_action( 'customize_register', 'minecraft_modern_customize_register' );
-
-
-// =========================================================================
-// DYNAMISCHES CSS – FIX: Google Font via wp_enqueue_style(), nicht
in wp_head
-// =========================================================================
-function minecraft_modern_enqueue_dynamic_styles() {
- $font = get_theme_mod( 'slider_font_family', 'Raleway' );
-
- // Google Font sauber einbinden
- $font_url = 'https://fonts.googleapis.com/css2?family=' . urlencode($font) . ':wght@400;600;700&display=swap';
- wp_enqueue_style( 'minecraft-modern-google-font', $font_url, array(), null );
-
- // Dynamisches CSS als inline style
- $accent_color = get_theme_mod( 'primary_accent_color', '#00d4ff' );
- $slider_color = get_theme_mod( 'slider_font_color', '#ffffff' );
- $slider_size_setting = get_theme_mod( 'slider_font_size', 'mittel' );
- $header_height_setting = get_theme_mod( 'header_height', 'mittel' );
-
- $height_map = array( 'klein' => '200px', 'mittel' => '300px', 'gross' => '400px' );
- $header_height_value = isset($height_map[$header_height_setting]) ? $height_map[$header_height_setting] : '300px';
-
- $font_sizes = array(
- 'klein' => array( 'title' => '2.5rem', 'subtitle' => '1.2rem' ),
- 'mittel' => array( 'title' => '3.5rem', 'subtitle' => '1.4rem' ),
- 'gross' => array( 'title' => '4.5rem', 'subtitle' => '1.6rem' ),
- 'extra-gross' => array( 'title' => '5.5rem', 'subtitle' => '1.8rem' ),
- );
- $sizes = isset($font_sizes[$slider_size_setting]) ? $font_sizes[$slider_size_setting] : $font_sizes['mittel'];
-
- $css = "
- :root {
- --primary-accent: " . esc_attr($accent_color) . ";
- --header-height: " . esc_attr($header_height_value) . ";
- }
- .slider-title, .slider-subtitle, .hero-title, .hero-subtitle, .hero-button-1, .hero-button-2 {
- font-family: '" . esc_attr($font) . "', sans-serif;
- color: " . esc_attr($slider_color) . ";
- }
- .slider-title, .hero-title { font-size: " . esc_attr($sizes['title']) . "; }
- .slider-subtitle, .hero-subtitle { font-size: " . esc_attr($sizes['subtitle']) . "; }
- .site-header { border-bottom: 4px solid var(--primary-accent); }
- .hero-slider { border-bottom: 4px solid var(--primary-accent); }
- .site-footer { border-top: 4px solid var(--primary-accent); }
- ";
-
- wp_add_inline_style( 'minecraft-modern-style', $css );
-}
-add_action( 'wp_enqueue_scripts', 'minecraft_modern_enqueue_dynamic_styles', 20 );
-
-
-// =========================================================================
-// PRESET LOGIC (JS im Customizer)
-// =========================================================================
-function minecraft_preset_customize_js() { ?>
-
- direkt in wp_head
+ * - slider_loop Setting ergänzt (war in slider-init.js referenziert, aber nie definiert)
+ * - Scroll-to-Top Toggle ergänzt
+ * - footer_copyright Default mit aktuellem Jahr zur Laufzeit
+ * - Import_Export_Control Klasse aus dem Callback extrahiert
+ */
+
+// =========================================================================
+// Import/Export Control – außerhalb des Callbacks definiert
+// =========================================================================
+if ( class_exists('WP_Customize_Control') && ! class_exists('MM_Import_Export_Control') ) :
+class MM_Import_Export_Control extends WP_Customize_Control {
+ public $type = 'mm_import_export';
+
+ public function render_content() {
+ $export_url = admin_url('admin-post.php?action=export_theme_settings');
+ $nonce = wp_create_nonce('theme-import-nonce');
+ ?>
+
+
+
+
+
+
+
+ 📦 Was wird gesichert:
+ ✓ Customizer-Einstellungen (Farben, Social Links, Menü-Design, etc.)
+ ✓ Livestream API Keys (YouTube, Twitch)
+ ✓ Homepage-Seite (Titel, Inhalt, Highlight-Bild)
+ ✓ Navigation Menüs inkl. aller Items & Struktur
+ ✓ Widget-Konfigurationen
+ ✓ Team-Mitglieder (mit UUID, Avatar, Banner)
+ ✓ FAQ-Einträge & Kategorien
+ ✓ Custom CSS
+ ✓ Announcement-Bar Einstellungen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ⚠️
+
+
+
+
+ add_section( 'assistant_settings', array(
+ 'title' => __( 'Virtueller Assistent', 'minecraft-modern-theme' ),
+ 'priority' => 80,
+ 'description' => __( 'Steuert den virtuellen Assistenten im Frontend. Avatar basiert auf Minecraft-UUID.', 'minecraft-modern-theme' ),
+ ) );
+
+ $wp_customize->add_setting( 'assistant_enabled', array(
+ 'default' => false,
+ 'sanitize_callback' => 'wp_validate_boolean',
+ ) );
+ $wp_customize->add_control( 'assistant_enabled', array(
+ 'label' => __( 'Virtuellen Assistenten aktivieren', 'minecraft-modern-theme' ),
+ 'section' => 'assistant_settings',
+ 'type' => 'checkbox',
+ ) );
+
+ $wp_customize->add_setting( 'assistant_minecraft_uuid', array(
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ ) );
+ $wp_customize->add_control( 'assistant_minecraft_uuid', array(
+ 'label' => __( 'Minecraft UUID für Avatar', 'minecraft-modern-theme' ),
+ 'section' => 'assistant_settings',
+ 'type' => 'text',
+ 'description' => __( 'Gib die Minecraft-UUID für den Avatar des Assistenten ein.', 'minecraft-modern-theme' ),
+ ) );
+
+ $wp_customize->add_setting( 'assistant_avatar_view', array(
+ 'default' => 'head',
+ 'sanitize_callback' => function ( $v ) {
+ return in_array( $v, array( 'head', 'body', '3dhead' ), true ) ? $v : 'head';
+ },
+ ) );
+ $wp_customize->add_control( 'assistant_avatar_view', array(
+ 'label' => __( 'Avatar-Ansicht', 'minecraft-modern-theme' ),
+ 'section' => 'assistant_settings',
+ 'type' => 'select',
+ 'choices' => array(
+ 'head' => __( 'Kopf', 'minecraft-modern-theme' ),
+ 'body' => __( 'Ganzkörper', 'minecraft-modern-theme' ),
+ '3dhead' => __( '3D Kopf', 'minecraft-modern-theme' ),
+ ),
+ 'description' => __( 'Wähle, wie der Minecraft-Avatar im Assistenten angezeigt wird.', 'minecraft-modern-theme' ),
+ ) );
+
+ // BUG-FIX: assistant_position war in assistant-widget.php in einem eigenen
+ // customize_register-Hook registriert – also BEVOR diese Section existierte.
+ // Jetzt korrekt hier innerhalb von minecraft_modern_customize_register().
+ $wp_customize->add_setting( 'assistant_position', array(
+ 'default' => 'bottom_right',
+ 'transport' => 'refresh',
+ 'sanitize_callback' => function ( $v ) {
+ $allowed = array( 'bottom_right', 'bottom_left', 'top_right', 'top_left' );
+ return in_array( $v, $allowed, true ) ? $v : 'bottom_right';
+ },
+ ) );
+ $wp_customize->add_control( 'assistant_position', array(
+ 'label' => __( 'Position des Assistenten', 'minecraft-modern-theme' ),
+ 'section' => 'assistant_settings',
+ 'type' => 'select',
+ 'choices' => array(
+ 'bottom_right' => __( 'Unten rechts', 'minecraft-modern-theme' ),
+ 'bottom_left' => __( 'Unten links', 'minecraft-modern-theme' ),
+ 'top_right' => __( 'Oben rechts', 'minecraft-modern-theme' ),
+ 'top_left' => __( 'Oben links', 'minecraft-modern-theme' ),
+ ),
+ ) );
+
+ // =========================================================================
+ // 1. HEADER SLIDER
+ // =========================================================================
+ $wp_customize->add_section( 'header_slider', array(
+ 'title' => __('Header Slider', 'minecraft-modern-theme'),
+ 'priority' => 20,
+ 'description' => __('Konfiguriere den großen Slider auf der Startseite.', 'minecraft-modern-theme'),
+ ) );
+
+ $wp_customize->add_setting( 'slider_enabled', array( 'default' => false, 'transport' => 'refresh', 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'slider_enabled', array( 'label' => __('Header Slider aktivieren', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'checkbox' ) );
+
+ // FIX: slider_loop war in slider-init.js als sliderSettings.loop referenziert, aber nie definiert
+ $wp_customize->add_setting( 'slider_loop', array( 'default' => true, 'transport' => 'refresh', 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'slider_loop', array(
+ 'label' => __('Slider Endlos-Loop aktivieren', 'minecraft-modern-theme'),
+ 'description' => __('Der Slider springt nach dem letzten Slide wieder zum ersten zurück.', 'minecraft-modern-theme'),
+ 'section' => 'header_slider',
+ 'type' => 'checkbox',
+ ) );
+
+ for ( $i = 1; $i <= 5; $i++ ) {
+ $wp_customize->add_setting( 'slider_image_' . $i, array( 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'slider_image_' . $i, array(
+ 'label' => sprintf( __('Banner %d - Bild', 'minecraft-modern-theme'), $i ), 'section' => 'header_slider',
+ ) ) );
+ $wp_customize->add_setting( 'slider_title_' . $i, array( 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'slider_title_' . $i, array( 'label' => sprintf( __('Banner %d - Titel', 'minecraft-modern-theme'), $i ), 'section' => 'header_slider', 'type' => 'text' ) );
+ $wp_customize->add_setting( 'slider_subtitle_' . $i, array( 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'slider_subtitle_' . $i, array( 'label' => sprintf( __('Banner %d - Untertitel', 'minecraft-modern-theme'), $i ), 'section' => 'header_slider', 'type' => 'text' ) );
+ }
+
+ $wp_customize->add_setting( 'slider_font_family', array( 'default' => 'Raleway', 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'slider_font_family', array(
+ 'label' => __('Schriftart', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'select',
+ 'choices' => array( 'Raleway' => 'Raleway', 'Poppins' => 'Poppins', 'Montserrat' => 'Montserrat', 'Oswald' => 'Oswald', 'Roboto' => 'Roboto', 'Lato' => 'Lato' ),
+ ) );
+
+ $wp_customize->add_setting( 'slider_font_size', array( 'default' => 'mittel', 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'slider_font_size', array(
+ 'label' => __('Schriftgröße', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'select',
+ 'choices' => array( 'klein' => __('Klein', 'minecraft-modern-theme'), 'mittel' => __('Mittel', 'minecraft-modern-theme'), 'gross' => __('Groß', 'minecraft-modern-theme'), 'extra-gross' => __('Extra Groß', 'minecraft-modern-theme') ),
+ ) );
+
+ $wp_customize->add_setting( 'slider_font_color', array( 'default' => '#ffffff', 'sanitize_callback' => 'sanitize_hex_color' ) );
+ $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'slider_font_color', array(
+ 'label' => __('Schriftfarbe', 'minecraft-modern-theme'), 'section' => 'header_slider',
+ ) ) );
+
+ $wp_customize->add_setting( 'header_height', array( 'default' => 'mittel', 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'header_height', array(
+ 'label' => __('Header-Höhe', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'select',
+ 'choices' => array( 'klein' => __('Klein', 'minecraft-modern-theme'), 'mittel' => __('Mittel', 'minecraft-modern-theme'), 'gross' => __('Groß', 'minecraft-modern-theme') ),
+ ) );
+
+ $wp_customize->add_setting( 'slider_hide_arrows', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'slider_hide_arrows', array( 'label' => __('Pfeile ausblenden', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'checkbox' ) );
+
+ $wp_customize->add_setting( 'slider_hide_pagination', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'slider_hide_pagination', array( 'label' => __('Paginierung (Punkte) ausblenden', 'minecraft-modern-theme'), 'section' => 'header_slider', 'type' => 'checkbox' ) );
+
+
+ // =========================================================================
+ // 2. HERO SECTION (Fallback)
+ // =========================================================================
+ $wp_customize->add_section( 'hero_section', array(
+ 'title' => __('Startseiten-Hero (wenn Slider deaktiviert)', 'minecraft-modern-theme'),
+ 'priority' => 21,
+ ) );
+
+ $wp_customize->add_setting( 'hero_title', array( 'default' => __('Willkommen auf unserem Server', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'hero_title', array( 'label' => __('Haupttitel', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
+ $wp_customize->add_setting( 'hero_subtitle', array( 'default' => __('Trete einer Community voller Abenteuer bei.', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'hero_subtitle', array( 'label' => __('Untertitel', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
+ $wp_customize->add_setting( 'hero_bg_image', array( 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'hero_bg_image', array( 'label' => __('Hintergrundbild', 'minecraft-modern-theme'), 'section' => 'hero_section' ) ) );
+ $wp_customize->add_setting( 'hero_button_1_text', array( 'default' => __('Zum Forum', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'hero_button_1_text', array( 'label' => __('Button 1 Text', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
+ $wp_customize->add_setting( 'hero_button_1_url', array( 'default' => '#', 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( 'hero_button_1_url', array( 'label' => __('Button 1 URL', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'url' ) );
+ $wp_customize->add_setting( 'hero_button_2_text', array( 'default' => __('Zum Teamspeak', 'minecraft-modern-theme'), 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( 'hero_button_2_text', array( 'label' => __('Button 2 Text', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'text' ) );
+ $wp_customize->add_setting( 'hero_button_2_url', array( 'default' => '#', 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( 'hero_button_2_url', array( 'label' => __('Button 2 URL', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'url' ) );
+ $wp_customize->add_setting( 'show_home_title', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'show_home_title', array( 'label' => __('Seitentitel "Home" anzeigen', 'minecraft-modern-theme'), 'section' => 'hero_section', 'type' => 'checkbox' ) );
+
+
+ // =========================================================================
+ // 3. FARBEN & DARSTELLUNG
+ // =========================================================================
+ $wp_customize->add_section( 'theme_appearance_settings', array(
+ 'title' => __('Farben & Darstellung', 'minecraft-modern-theme'), 'priority' => 30,
+ ) );
+
+ $wp_customize->add_setting( 'theme_color_preset', array( 'default' => 'classic', 'sanitize_callback' => 'sanitize_key', 'transport' => 'refresh' ) );
+ $wp_customize->add_control( 'theme_color_preset', array(
+ 'label' => __('Theme Preset (Farbschema)', 'minecraft-modern-theme'),
+ 'section' => 'theme_appearance_settings',
+ 'type' => 'select',
+ 'priority' => 1,
+ 'choices' => array(
+ 'classic' => __('Classic Minecraft (Diamant-Blau)', 'minecraft-modern-theme'),
+ 'nether' => __('Nether (Lava-Rot)', 'minecraft-modern-theme'),
+ 'end' => __('The End (Ender-Purpur)', 'minecraft-modern-theme'),
+ ),
+ ) );
+
+ $wp_customize->add_setting( 'primary_accent_color', array( 'default' => '#00d4ff', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'refresh' ) );
+ $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'primary_accent_color', array( 'label' => __('Akzentfarbe', 'minecraft-modern-theme'), 'section' => 'theme_appearance_settings' ) ) );
+
+ $wp_customize->add_setting( 'default_theme_mode', array( 'default' => 'dark', 'sanitize_callback' => 'sanitize_key' ) );
+ $wp_customize->add_control( 'default_theme_mode', array(
+ 'label' => __('Standard-Theme-Modus', 'minecraft-modern-theme'),
+ 'section' => 'theme_appearance_settings',
+ 'type' => 'radio',
+ 'choices' => array( 'dark' => __('Dark Mode', 'minecraft-modern-theme'), 'light' => __('Light Mode', 'minecraft-modern-theme') ),
+ ) );
+
+ // FIX: Scroll-to-Top war nie im Customizer steuerbar
+ $wp_customize->add_setting( 'show_scroll_to_top', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'show_scroll_to_top', array(
+ 'label' => __('Scroll-to-Top Button anzeigen', 'minecraft-modern-theme'),
+ 'description' => __('Zeigt einen Button unten rechts zum Hochscrollen an.', 'minecraft-modern-theme'),
+ 'section' => 'theme_appearance_settings',
+ 'type' => 'checkbox',
+ ) );
+
+
+ // =========================================================================
+ // 4. SIDEBAR
+ // =========================================================================
+ $wp_customize->add_section( 'sidebar_settings', array( 'title' => __('Sidebar Einstellungen', 'minecraft-modern-theme'), 'priority' => 35 ) );
+ $wp_customize->add_setting( 'homepage_sidebar_enabled', array( 'default' => false, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'homepage_sidebar_enabled', array( 'label' => __('Sidebar auf Startseite aktivieren', 'minecraft-modern-theme'), 'section' => 'sidebar_settings', 'type' => 'checkbox' ) );
+ $wp_customize->add_setting( 'homepage_sidebar_position', array( 'default' => 'right', 'sanitize_callback' => 'sanitize_key' ) );
+ $wp_customize->add_control( 'homepage_sidebar_position', array(
+ 'label' => __('Sidebar Position', 'minecraft-modern-theme'), 'section' => 'sidebar_settings', 'type' => 'select',
+ 'choices' => array( 'left' => __('Links', 'minecraft-modern-theme'), 'right' => __('Rechts', 'minecraft-modern-theme') ),
+ ) );
+
+
+ // =========================================================================
+ // 5. SOCIAL MEDIA
+ // =========================================================================
+ $wp_customize->add_section( 'social_links', array( 'title' => __('Social Media Links', 'minecraft-modern-theme'), 'priority' => 40 ) );
+ $social_platforms = array(
+ 'bluesky' => 'BlueSky', 'discord' => 'Discord', 'youtube' => 'YouTube', 'twitter' => 'Twitter (X)',
+ 'facebook' => 'Facebook', 'instagram' => 'Instagram', 'tiktok' => 'TikTok',
+ 'twitch' => 'Twitch', 'steam' => 'Steam', 'github' => 'GitHub',
+ 'linkedin' => 'LinkedIn', 'pinterest' => 'Pinterest', 'reddit' => 'Reddit',
+ 'mastodon' => 'Mastodon', 'threads' => 'Threads', 'kickstarter' => 'Kickstarter',
+ 'teamspeak' => 'Teamspeak', 'spotify' => 'Spotify', 'stoat' => 'Stoat',
+ );
+ foreach ( $social_platforms as $key => $label ) {
+ $wp_customize->add_setting( 'social_' . $key, array( 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( 'social_' . $key, array( 'label' => $label . ' URL', 'section' => 'social_links', 'type' => 'url' ) );
+ }
+
+ // =========================================================================
+ // 6. FOOTER
+ // =========================================================================
+ $wp_customize->add_section( 'footer_settings', array( 'title' => __('Footer-Einstellungen', 'minecraft-modern-theme'), 'priority' => 50 ) );
+
+ // FIX: Default mit aktuellem Jahr zur Laufzeit auswerten, nicht bei class-load
+ $wp_customize->add_setting( 'footer_copyright', array(
+ 'default' => '', // Leer = dynamisch berechnet in footer.php
+ 'sanitize_callback' => 'wp_kses_post',
+ ) );
+ $wp_customize->add_control( 'footer_copyright', array(
+ 'label' => __('Copyright-Text', 'minecraft-modern-theme'),
+ 'description' => __('Leer lassen für automatischen Text mit aktuellem Jahr.', 'minecraft-modern-theme'),
+ 'section' => 'footer_settings',
+ 'type' => 'textarea',
+ ) );
+
+ $wp_customize->add_setting( 'footer_impressum_url', array( 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( 'footer_impressum_url', array( 'label' => __('URL für Impressum', 'minecraft-modern-theme'), 'section' => 'footer_settings', 'type' => 'url' ) );
+ $wp_customize->add_setting( 'footer_datenschutz_url', array( 'sanitize_callback' => 'esc_url_raw' ) );
+ $wp_customize->add_control( 'footer_datenschutz_url', array( 'label' => __('URL für Datenschutz', 'minecraft-modern-theme'), 'section' => 'footer_settings', 'type' => 'url' ) );
+ $wp_customize->add_setting( 'show_footer_credit', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'show_footer_credit', array( 'label' => __('Footer-Credit anzeigen', 'minecraft-modern-theme'), 'section' => 'footer_settings', 'type' => 'checkbox' ) );
+
+
+ // =========================================================================
+ // 7. FAQ & TEAM
+ // =========================================================================
+ $wp_customize->add_section( 'faq_settings', array( 'title' => __('FAQ Einstellungen', 'minecraft-modern-theme'), 'priority' => 60 ) );
+ $wp_customize->add_setting( 'faq_enabled', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'faq_enabled', array( 'label' => __('FAQ System aktivieren', 'minecraft-modern-theme'), 'section' => 'faq_settings', 'type' => 'checkbox' ) );
+
+ $wp_customize->add_section( 'team_settings', array( 'title' => __('Team Einstellungen', 'minecraft-modern-theme'), 'priority' => 65 ) );
+ $wp_customize->add_setting( 'team_enabled', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean' ) );
+ $wp_customize->add_control( 'team_enabled', array( 'label' => __('Team Showcase aktivieren', 'minecraft-modern-theme'), 'section' => 'team_settings', 'type' => 'checkbox' ) );
+
+
+ // =========================================================================
+ // 8. LOGIN
+ // =========================================================================
+ $wp_customize->add_section( 'login_settings', array( 'title' => __('Login-Einstellungen', 'minecraft-modern-theme'), 'priority' => 70 ) );
+ $wp_customize->add_setting( 'login_background_image', array( 'sanitize_callback' => 'esc_url_raw', 'transport' => 'refresh' ) );
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'login_background_image', array( 'label' => __('Login-Hintergrundbild', 'minecraft-modern-theme'), 'section' => 'login_settings' ) ) );
+ $wp_customize->add_setting( 'login_logo', array( 'sanitize_callback' => 'esc_url_raw', 'transport' => 'refresh' ) );
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'login_logo', array( 'label' => __('Login-Logo', 'minecraft-modern-theme'), 'section' => 'login_settings' ) ) );
+
+ for ( $i = 1; $i <= 5; $i++ ) {
+ $wp_customize->add_setting( 'login_avatar_uuid_' . $i, array( 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'refresh' ) );
+ $wp_customize->add_control( 'login_avatar_uuid_' . $i, array(
+ 'label' => sprintf( __('Avatar %d UUID', 'minecraft-modern-theme'), $i ),
+ 'section' => 'login_settings',
+ 'type' => 'text',
+ ) );
+ }
+
+ $wp_customize->add_setting( 'login_avatar_slider_speed', array( 'default' => 4, 'sanitize_callback' => 'absint', 'transport' => 'refresh' ) );
+ $wp_customize->add_control( 'login_avatar_slider_speed', array(
+ 'label' => __('Avatar-Wechsel (Sekunden)', 'minecraft-modern-theme'),
+ 'section' => 'login_settings',
+ 'type' => 'number',
+ 'input_attrs' => array( 'min' => 2, 'max' => 10, 'step' => 1 ),
+ ) );
+
+
+ // =========================================================================
+ // 8.5. VIDEO / LIVESTREAM EINSTELLUNGEN
+ // =========================================================================
+ $wp_customize->add_section( 'video_livestream_settings', array(
+ 'title' => __('Video & Livestream', 'minecraft-modern-theme'),
+ 'description' => __('Einstellungen für YouTube Livestream-Erkennung. Hauptmethode: Livestream-Posts unter "Livestreams" erstellen. Optional: Zusätzlichen Hauptkanal hier eintragen.', 'minecraft-modern-theme'),
+ 'priority' => 75,
+ ) );
+
+ $wp_customize->add_setting( 'youtube_api_key', array(
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'youtube_api_key', array(
+ 'label' => __('YouTube API Key', 'minecraft-modern-theme'),
+ 'description' => __('Erforderlich für automatische YouTube Live-Erkennung.
Hier API Key erstellen ', 'minecraft-modern-theme'),
+ 'section' => 'video_livestream_settings',
+ 'type' => 'text',
+ 'input_attrs' => array(
+ 'placeholder' => 'AIzaSyD...',
+ ),
+ ) );
+
+ $wp_customize->add_setting( 'twitch_client_id', array(
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'twitch_client_id', array(
+ 'label' => __('Twitch Client ID', 'minecraft-modern-theme'),
+ 'description' => __('Erforderlich für Twitch Live-Erkennung.
Hier App erstellen ', 'minecraft-modern-theme'),
+ 'section' => 'video_livestream_settings',
+ 'type' => 'text',
+ 'input_attrs' => array(
+ 'placeholder' => 'xxxxxxxxxxxxxx',
+ ),
+ ) );
+
+ $wp_customize->add_setting( 'twitch_client_secret', array(
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'twitch_client_secret', array(
+ 'label' => __('Twitch Client Secret', 'minecraft-modern-theme'),
+ 'description' => __('Nur für Live-Prüfung. Wird serverseitig genutzt.', 'minecraft-modern-theme'),
+ 'section' => 'video_livestream_settings',
+ 'type' => 'text',
+ 'input_attrs' => array(
+ 'placeholder' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+ ),
+ ) );
+
+ // =========================================================================
+ // 9. EXPORT / IMPORT
+ // =========================================================================
+ $wp_customize->add_section( 'theme_mods_import_export', array(
+ 'title' => __('Einstellungen sichern', 'minecraft-modern-theme'),
+ 'priority' => 999,
+ ) );
+ $wp_customize->add_setting( 'import_export_placeholder', array( 'sanitize_callback' => 'sanitize_text_field' ) );
+ $wp_customize->add_control( new MM_Import_Export_Control( $wp_customize, 'import_export_placeholder', array(
+ 'section' => 'theme_mods_import_export',
+ ) ) );
+}
+add_action( 'customize_register', 'minecraft_modern_customize_register' );
+
+
+// =========================================================================
+// DYNAMISCHES CSS – Slider-Schrift wird lokal eingebunden (DSGVO)
+// =========================================================================
+function minecraft_modern_enqueue_dynamic_styles() {
+ $font = get_theme_mod( 'slider_font_family', 'Raleway' );
+
+ // Lokale Schrift statt fonts.googleapis.com (siehe mm_enqueue_local_font()).
+ // Fällt die Schrift aus, greift die Basis-Schrift bzw. sans-serif aus dem CSS.
+ mm_enqueue_local_font( $font );
+
+ // Dynamisches CSS als inline style
+ $accent_color = get_theme_mod( 'primary_accent_color', '#00d4ff' );
+ $slider_color = get_theme_mod( 'slider_font_color', '#ffffff' );
+ $slider_size_setting = get_theme_mod( 'slider_font_size', 'mittel' );
+ $header_height_setting = get_theme_mod( 'header_height', 'mittel' );
+
+ $height_map = array( 'klein' => '200px', 'mittel' => '300px', 'gross' => '400px' );
+ $header_height_value = isset($height_map[$header_height_setting]) ? $height_map[$header_height_setting] : '300px';
+
+ $font_sizes = array(
+ 'klein' => array( 'title' => '2.5rem', 'subtitle' => '1.2rem' ),
+ 'mittel' => array( 'title' => '3.5rem', 'subtitle' => '1.4rem' ),
+ 'gross' => array( 'title' => '4.5rem', 'subtitle' => '1.6rem' ),
+ 'extra-gross' => array( 'title' => '5.5rem', 'subtitle' => '1.8rem' ),
+ );
+ $sizes = isset($font_sizes[$slider_size_setting]) ? $font_sizes[$slider_size_setting] : $font_sizes['mittel'];
+
+ $css = "
+ :root {
+ --primary-accent: " . esc_attr($accent_color) . ";
+ --header-height: " . esc_attr($header_height_value) . ";
+ }
+ .slider-title, .slider-subtitle, .hero-title, .hero-subtitle, .hero-button-1, .hero-button-2 {
+ font-family: '" . esc_attr($font) . "', sans-serif;
+ color: " . esc_attr($slider_color) . ";
+ }
+ .slider-title, .hero-title { font-size: " . esc_attr($sizes['title']) . "; }
+ .slider-subtitle, .hero-subtitle { font-size: " . esc_attr($sizes['subtitle']) . "; }
+ .site-header { border-bottom: 4px solid var(--primary-accent); }
+ .hero-slider { border-bottom: 4px solid var(--primary-accent); }
+ .site-footer { border-top: 4px solid var(--primary-accent); }
+ ";
+
+ wp_add_inline_style( 'minecraft-modern-style', $css );
+}
+add_action( 'wp_enqueue_scripts', 'minecraft_modern_enqueue_dynamic_styles', 20 );
+
+
+// =========================================================================
+// PRESET LOGIC (JS im Customizer)
+// =========================================================================
+function minecraft_preset_customize_js() { ?>
+
+ array(
+ 'name' => __( 'FAQs', 'minecraft-modern-theme' ),
+ 'singular_name' => __( 'FAQ', 'minecraft-modern-theme' ),
+ 'add_new' => __( 'Neue FAQ hinzufügen', 'minecraft-modern-theme' ),
+ 'add_new_item' => __( 'Neue FAQ hinzufügen', 'minecraft-modern-theme' ),
+ 'edit_item' => __( 'FAQ bearbeiten', 'minecraft-modern-theme' ),
+ 'new_item' => __( 'Neue FAQ', 'minecraft-modern-theme' ),
+ 'view_item' => __( 'FAQ ansehen', 'minecraft-modern-theme' ),
+ 'search_items' => __( 'FAQs durchsuchen', 'minecraft-modern-theme' ),
+ 'not_found' => __( 'Keine FAQs gefunden', 'minecraft-modern-theme' ),
+ 'not_found_in_trash' => __( 'Keine FAQs im Papierkorb gefunden', 'minecraft-modern-theme' ),
+ 'all_items' => __( 'Alle FAQs', 'minecraft-modern-theme' ),
+ ),
+ 'public' => true,
+ 'has_archive' => true,
+ 'menu_icon' => 'dashicons-format-chat',
+ 'supports' => array( 'title', 'editor', 'page-attributes' ),
+ 'rewrite' => array( 'slug' => 'faq' ),
+ 'show_in_rest' => true,
+ ) );
+ register_taxonomy( 'faq_category', 'faq', array(
+ 'label' => __( 'FAQ Kategorien', 'minecraft-modern-theme' ),
+ 'rewrite' => array( 'slug' => 'faq-kategorie' ),
+ 'hierarchical' => true,
+ 'show_in_rest' => true,
+ ) );
+ }
+}
+add_action( 'init', 'create_faq_post_type' );
+
+// =============================================================================
+// FAQ-Seitenerstellung
+// =============================================================================
+
+function create_faq_page_automatically() {
+ if ( ! get_theme_mod( 'faq_enabled', true ) ) return;
+
+ // BUG-FIX: get_page_by_title() ist seit WP 6.2 deprecated. Ersetzt durch WP_Query.
+ $faq_query = new WP_Query( array(
+ 'post_type' => 'page',
+ 'title' => 'FAQ',
+ 'post_status' => 'publish',
+ 'posts_per_page' => 1,
+ 'no_found_rows' => true,
+ 'update_post_meta_cache' => false,
+ 'update_post_term_cache' => false,
+ ) );
+ if ( $faq_query->have_posts() ) return;
+
+ wp_insert_post( array(
+ 'post_title' => 'FAQ',
+ 'post_content' => 'Diese Seite zeigt alle FAQs an. Der Inhalt wird automatisch generiert.',
+ 'post_status' => 'publish',
+ 'post_type' => 'page',
+ 'post_author' => 1,
+ ) );
+}
+add_action( 'customize_save_after', 'create_faq_page_automatically' );
+
+
+function load_faq_page_template( $template ) {
+ if ( get_theme_mod( 'faq_enabled', true ) && is_page() ) {
+ global $post;
+ if ( $post && $post->post_title === 'FAQ' ) {
+ // BUG-FIX: get_template_directory() erzwang das Parent-Template und
+ // ignorierte ein archive-faq.php im Child-Theme. locate_template()
+ // bevorzugt das Child-Theme und fällt sonst aufs Parent zurück.
+ $t = locate_template( 'archive-faq.php' );
+ if ( $t ) return $t;
+ }
+ }
+ return $template;
+}
+add_filter( 'template_include', 'load_faq_page_template' );
diff --git a/Minecraft-Modern-Theme/inc/frontpage.php b/Minecraft-Modern-Theme/inc/frontpage.php
new file mode 100644
index 0000000..792b2a7
--- /dev/null
+++ b/Minecraft-Modern-Theme/inc/frontpage.php
@@ -0,0 +1,58 @@
+ 'page',
+ 'title' => 'Home',
+ 'post_status' => 'publish',
+ 'posts_per_page' => 1,
+ 'no_found_rows' => true,
+ 'update_post_meta_cache' => false,
+ 'update_post_term_cache' => false,
+ ) );
+ $home_page = $home_query->have_posts() ? $home_query->posts[0] : null;
+ if ( ! $home_page ) {
+ $home_page_id = wp_insert_post( array(
+ 'post_title' => 'Home',
+ 'post_content' => 'Diese Seite dient als statische Startseite.',
+ 'post_status' => 'publish',
+ 'post_type' => 'page',
+ 'post_author' => 1,
+ ) );
+ } else {
+ $home_page_id = $home_page->ID;
+ }
+ if ( $home_page_id ) {
+ update_option( 'show_on_front', 'page' );
+ update_option( 'page_on_front', $home_page_id );
+ }
+ }
+}
+add_action( 'after_switch_theme', 'set_static_front_page_automatically' );
+
+
+function add_home_body_class( $classes ) {
+ if ( is_front_page() && ! get_theme_mod( 'show_home_title', true ) ) {
+ $classes[] = 'home-title-hidden';
+ }
+ return $classes;
+}
+add_filter( 'body_class', 'add_home_body_class' );
diff --git a/Minecraft-Modern-Theme/inc/header-nav.php b/Minecraft-Modern-Theme/inc/header-nav.php
new file mode 100644
index 0000000..c260961
--- /dev/null
+++ b/Minecraft-Modern-Theme/inc/header-nav.php
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Panel –
+ // der Hamburger wird dort nicht gebraucht und verursacht JS-Konflikte.
+ if ( $menu_style !== 'sidebar' ) : ?>
+
+
+ 'primary',
+ 'container' => false,
+ 'menu_class' => 'primary-menu',
+ 'fallback_cb' => false,
+ ) ); ?>
+
+ 'fab fa-bluesky', 'discord' => 'fab fa-discord', 'youtube' => 'fab fa-youtube',
+ 'twitter' => 'fab fa-x-twitter', 'facebook' => 'fab fa-facebook-f',
+ 'instagram' => 'fab fa-instagram', 'tiktok' => 'fab fa-tiktok',
+ 'twitch' => 'fab fa-twitch', 'steam' => 'fab fa-steam',
+ 'github' => 'fab fa-github', 'linkedin' => 'fab fa-linkedin-in',
+ 'pinterest' => 'fab fa-pinterest-p', 'reddit' => 'fab fa-reddit-alien',
+ 'mastodon' => 'fab fa-mastodon', 'threads' => 'fab fa-threads',
+ 'kickstarter' => 'fab fa-kickstarter', 'teamspeak' => 'fab fa-teamspeak', 'spotify' => 'fab fa-spotify',
+ 'stoat' => 'fab fa-diaspora',
+ ); ?>
+
+add_section( 'header_menu_style_section', array(
+ 'title' => __( 'Menü-Design', 'minecraft-modern-theme' ),
+ 'priority' => 30,
+ ) );
+ $wp_customize->add_setting( 'header_menu_style', array(
+ 'default' => 'classic',
+ 'sanitize_callback' => 'sanitize_text_field',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'header_menu_style', array(
+ 'label' => __( 'Menü-Layout wählen', 'minecraft-modern-theme' ),
+ 'section' => 'header_menu_style_section',
+ 'type' => 'select',
+ 'choices' => array(
+ 'classic' => __( '① Classic – Logo links, Menü Mitte, Icons rechts', 'minecraft-modern-theme' ),
+ 'centered' => __( '② Zentriert – Logo oben, Menü darunter', 'minecraft-modern-theme' ),
+ 'sidebar' => __( '③ Sidebar – Menü als vertikale Leiste', 'minecraft-modern-theme' ),
+ 'mega' => __( '④ Mega-Menü – breite Dropdown-Spalten', 'minecraft-modern-theme' ),
+ ),
+ ) );
+
+ // Branding-Position (gilt für alle Layouts)
+ $wp_customize->add_setting( 'sidebar_branding_position', array(
+ 'default' => 'left',
+ 'sanitize_callback' => 'sanitize_text_field',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'sidebar_branding_position', array(
+ 'label' => __( 'Logo/Titel Position', 'minecraft-modern-theme' ),
+ 'description' => __( 'Gilt für alle Menü-Layouts.', 'minecraft-modern-theme' ),
+ 'section' => 'header_menu_style_section',
+ 'type' => 'select',
+ 'choices' => array(
+ 'left' => __( 'Links', 'minecraft-modern-theme' ),
+ 'center' => __( 'Mitte', 'minecraft-modern-theme' ),
+ 'right' => __( 'Rechts', 'minecraft-modern-theme' ),
+ ),
+ ) );
+}
+add_action( 'customize_register', 'minecraft_modern_menu_style_customizer' );
+
+
+// === Sidebar-Menü JavaScript (nur wenn Sidebar-Layout aktiv) ===
+function minecraft_modern_sidebar_menu_script() {
+ if ( get_theme_mod( 'header_menu_style', 'classic' ) !== 'sidebar' ) return;
+ ?>
+
+ __( 'Beitrag Sidebar', 'minecraft-modern-theme' ),
+ 'id' => 'single-post-sidebar',
+ 'description' => __( 'Widget-Bereich für die Sidebar auf Einzelbeitrags-Seiten.', 'minecraft-modern-theme' ),
+ 'before_widget' => '',
+ 'before_title' => '
',
+ ) );
+}
+add_action( 'widgets_init', 'minecraft_modern_single_sidebar' );
+
+
+// === Single-Post Sidebar Render-Funktion ===
+function minecraft_modern_render_single_sidebar() {
+ if ( is_active_sidebar( 'single-post-sidebar' ) ) {
+ dynamic_sidebar( 'single-post-sidebar' );
+ } else {
+ ?>
+
+
+
+
+
+
+
+ add_section( 'single_sidebar_section', array(
+ 'title' => __( 'Beitrag Sidebar', 'minecraft-modern-theme' ),
+ 'priority' => 55,
+ ) );
+ $wp_customize->add_setting( 'single_sidebar_enabled', array(
+ 'default' => true,
+ 'sanitize_callback' => 'wp_validate_boolean',
+ ) );
+ $wp_customize->add_control( 'single_sidebar_enabled', array(
+ 'label' => __( 'Sidebar auf Einzelbeiträgen anzeigen', 'minecraft-modern-theme' ),
+ 'section' => 'single_sidebar_section',
+ 'type' => 'checkbox',
+ ) );
+ $wp_customize->add_setting( 'single_sidebar_position', array(
+ 'default' => 'right',
+ 'sanitize_callback' => 'sanitize_text_field',
+ ) );
+ $wp_customize->add_control( 'single_sidebar_position', array(
+ 'label' => __( 'Sidebar-Position', 'minecraft-modern-theme' ),
+ 'section' => 'single_sidebar_section',
+ 'type' => 'select',
+ 'choices' => array(
+ 'right' => __( 'Rechts', 'minecraft-modern-theme' ),
+ 'left' => __( 'Links', 'minecraft-modern-theme' ),
+ ),
+ ) );
+}
+add_action( 'customize_register', 'minecraft_modern_single_sidebar_customizer' );
diff --git a/Minecraft-Modern-Theme/inc/login-url.php b/Minecraft-Modern-Theme/inc/login-url.php
new file mode 100644
index 0000000..4a2b239
--- /dev/null
+++ b/Minecraft-Modern-Theme/inc/login-url.php
@@ -0,0 +1,251 @@
+ wp-login.php ausliefern
+ if ( $path === $slug ) {
+ global $pagenow, $error, $interim_login, $action, $user_login;
+ $pagenow = 'wp-login.php';
+ require_once ABSPATH . 'wp-login.php';
+ exit;
+ }
+
+ // 2) Alte Login-Adresse -> Startseite
+ if ( $path === 'wp-login.php' ) {
+ wp_safe_redirect( home_url( '/' ), 302 );
+ exit;
+ }
+
+ // 3) /wp-admin für Nicht-Angemeldete -> Startseite.
+ // admin-ajax.php und admin-post.php bleiben offen, sonst brechen
+ // Frontend-AJAX und der Authentik-OAuth-Rückkanal.
+ if ( $path === 'wp-admin' || strpos( $path, 'wp-admin/' ) === 0 ) {
+ $datei = basename( $path );
+ $erlaubt = array( 'admin-ajax.php', 'admin-post.php' );
+
+ if ( ! in_array( $datei, $erlaubt, true ) && ! is_user_logged_in() ) {
+ wp_safe_redirect( home_url( '/' ), 302 );
+ exit;
+ }
+ }
+}
+add_action( 'init', 'mm_login_slug_handle_request', 1 );
+
+
+// =========================================================================
+// CUSTOMIZER: Login-URL einstellen
+// =========================================================================
+
+function mm_login_slug_sanitize( $value ) {
+ $value = sanitize_title( (string) $value );
+ return in_array( $value, mm_login_slug_reserviert(), true ) ? '' : $value;
+}
+
+/**
+ * Prüft die Eingabe und meldet Kollisionen direkt im Customizer zurück,
+ * statt sie stillschweigend zu verwerfen.
+ */
+function mm_login_slug_validate( $validity, $value ) {
+ $value = sanitize_title( (string) $value );
+
+ if ( $value === '' ) {
+ return $validity; // leer ist erlaubt (= Funktion greift nicht)
+ }
+ if ( in_array( $value, mm_login_slug_reserviert(), true ) ) {
+ $validity->add( 'reserviert', __( 'Dieser Pfad ist von WordPress belegt. Bitte einen anderen wählen.', 'minecraft-modern-theme' ) );
+ return $validity;
+ }
+ // Kollision mit einer bestehenden Seite/Beitrag?
+ $vorhanden = get_page_by_path( $value, OBJECT, array( 'page', 'post' ) );
+ if ( $vorhanden ) {
+ $validity->add( 'belegt', sprintf(
+ /* translators: %s: Titel des kollidierenden Inhalts */
+ __( 'Der Pfad wird bereits von "%s" verwendet - diese Seite wäre dann nicht mehr erreichbar.', 'minecraft-modern-theme' ),
+ $vorhanden->post_title
+ ) );
+ }
+ return $validity;
+}
+add_filter( 'customize_validate_mm_login_slug', 'mm_login_slug_validate', 10, 2 );
+
+function mm_login_slug_customizer( $wp_customize ) {
+ $notfall = "define( 'MM_DISABLE_LOGIN_SLUG', true );";
+
+ $wp_customize->add_section( 'mm_login_url_section', array(
+ 'title' => __( 'Login-URL', 'minecraft-modern-theme' ),
+ 'priority' => 85,
+ 'description' => __( 'Ersetzt die Standard-Adresse /wp-login.php durch einen eigenen Pfad und reduziert so automatisierte Anmeldeversuche.', 'minecraft-modern-theme' )
+ . '
' . esc_html__( 'Notfall:', 'minecraft-modern-theme' ) . ' '
+ . esc_html__( 'Diese Zeile in die wp-config.php eintragen, dann ist /wp-login.php sofort wieder erreichbar:', 'minecraft-modern-theme' )
+ . '
' . esc_html( $notfall ) . '',
+ ) );
+
+ $wp_customize->add_setting( 'mm_login_slug', array(
+ 'default' => '',
+ 'sanitize_callback' => 'mm_login_slug_sanitize',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'mm_login_slug', array(
+ 'label' => __( 'Eigener Login-Pfad', 'minecraft-modern-theme' ),
+ 'description' => sprintf(
+ /* translators: %s: Beispiel-URL */
+ __( 'Nur der Pfad, ohne Schrägstriche. Ergibt: %s', 'minecraft-modern-theme' ),
+ '
' . esc_html( home_url( '/' ) ) . 'DEIN-PFAD/'
+ ),
+ 'section' => 'mm_login_url_section',
+ 'type' => 'text',
+ ) );
+
+ $wp_customize->add_setting( 'mm_login_slug_enabled', array(
+ 'default' => false,
+ 'sanitize_callback' => 'wp_validate_boolean',
+ 'transport' => 'refresh',
+ ) );
+ $wp_customize->add_control( 'mm_login_slug_enabled', array(
+ 'label' => __( 'Eigene Login-URL aktivieren', 'minecraft-modern-theme' ),
+ 'description' => __( 'Erst aktivieren, wenn oben ein Pfad eingetragen und gespeichert ist. Notiere dir die neue Adresse, bevor du dich abmeldest!', 'minecraft-modern-theme' ),
+ 'section' => 'mm_login_url_section',
+ 'type' => 'checkbox',
+ ) );
+}
+add_action( 'customize_register', 'mm_login_slug_customizer' );
+
+
+/**
+ * Hinweis im Adminbereich mit der aktuell gültigen Login-Adresse.
+ */
+function mm_login_slug_admin_notice() {
+ $slug = mm_login_slug_get();
+ if ( ! $slug || ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+ $screen = get_current_screen();
+ if ( ! $screen || ! in_array( $screen->id, array( 'dashboard', 'themes' ), true ) ) {
+ return;
+ }
+ printf(
+ '
',
+ esc_html__( 'Die Anmeldung erfolgt auf dieser Seite über:', 'minecraft-modern-theme' ),
+ esc_html( home_url( '/' . $slug . '/' ) )
+ );
+}
+add_action( 'admin_notices', 'mm_login_slug_admin_notice' );
diff --git a/Minecraft-Modern-Theme/inc/login.php b/Minecraft-Modern-Theme/inc/login.php
new file mode 100644
index 0000000..92ae133
--- /dev/null
+++ b/Minecraft-Modern-Theme/inc/login.php
@@ -0,0 +1,104 @@
+
');
+ });
+ " );
+
+ $slider_speed = get_theme_mod( 'login_avatar_slider_speed', 4 );
+ wp_localize_script( 'minecraft-avatar-slider-script', 'avatarSliderSettings', array(
+ 'speed' => $slider_speed * 1000,
+ ) );
+
+ $login_bg_image = get_theme_mod( 'login_background_image' );
+ if ( $login_bg_image ) {
+ wp_add_inline_style( 'minecraft-modern-login-style', "body.login { background-image: url('" . esc_url( $login_bg_image ) . "') !important; }" );
+ }
+ $logo_url = get_theme_mod( 'login_logo' );
+ if ( $logo_url ) {
+ wp_add_inline_style( 'minecraft-modern-login-style', ".login h1 a { background-image: url('" . esc_url( $logo_url ) . "') !important; }" );
+ }
+}
+add_action( 'login_enqueue_scripts', 'minecraft_modern_login_assets' );
+
+
+function add_minecraft_avatar_slider_to_login() {
+ $avatar_html = '