From c2e7ef1b46f8db68e072d349120b4e79e5df70d7 Mon Sep 17 00:00:00 2001 From: M_Viper Date: Thu, 19 Mar 2026 23:52:58 +0100 Subject: [PATCH] Upload file functions.php via GUI --- Minecraft-Modern-Theme/functions.php | 2770 +++++++++++++++++++------- 1 file changed, 2015 insertions(+), 755 deletions(-) diff --git a/Minecraft-Modern-Theme/functions.php b/Minecraft-Modern-Theme/functions.php index 639c419..8c04ee8 100644 --- a/Minecraft-Modern-Theme/functions.php +++ b/Minecraft-Modern-Theme/functions.php @@ -10,62 +10,57 @@ function minecraft_modern_setup() { add_theme_support( 'title-tag' ); add_theme_support( 'post-thumbnails' ); - // Logo-Unterstützung aktivieren (Maximale Flexibilität) add_theme_support( 'custom-logo', array( - 'height' => 9999, // Sehr hohe Werte, um den Crop-Dialog zu umgehen - 'width' => 9999, // Sehr hohe Werte, um den Crop-Dialog zu umgehen + 'height' => 9999, + 'width' => 9999, 'flex-height' => true, 'flex-width' => true, 'header_text' => array( 'site-title', 'site-description' ), ) ); - // Benutzerdefinierten Hintergrund aktivieren add_theme_support( 'custom-background' ); register_nav_menus( array( 'primary' => __( 'Hauptmenü', 'minecraft-modern-theme' ), 'footer' => __( 'Footer-Menü', 'minecraft-modern-theme' ), ) ); - add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption' ) ); + + // FIX: 'script' und 'style' ergänzt für sauberes HTML5-Output-Format + add_theme_support( 'html5', array( + 'search-form', 'comment-form', 'comment-list', + 'gallery', 'caption', 'script', 'style', + ) ); } add_action( 'after_setup_theme', 'minecraft_modern_setup' ); + // === Styles & Scripts laden === function minecraft_modern_scripts() { // Haupt-Stylesheet wp_enqueue_style( 'minecraft-modern-style', get_stylesheet_uri() ); - // Swiper.js CSS (von CDN) + // Swiper.js CSS wp_enqueue_style( 'swiper-css', 'https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css' ); - // JavaScript für den Header-Scroll-Effekt + // Header-Scroll + Suche Toggle wp_enqueue_script( 'minecraft-modern-header-script', get_template_directory_uri() . '/js/header-scroll.js', array(), - '1.0', + '1.1', true ); - // NEU: Navigation Script für Dropdown Menü laden + // Navigation (Dropdown + Außenklick-Schließen) wp_enqueue_script( 'minecraft-navigation', get_template_directory_uri() . '/js/navigation.js', - array(), // Keine Abhängigkeiten - '1.0', + array(), + '1.1', true ); - // NEU: Ankündigungs-Skript laden - wp_enqueue_script( - 'announcement-script', - get_template_directory_uri() . '/js/announcement.js', - array(), // Keine Abhängigkeiten - '1.3', // Version angehoben für Countdown Update - true - ); - - // Swiper.js JS (von CDN) + // Swiper.js wp_enqueue_script( 'swiper-js', 'https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.js', @@ -74,26 +69,26 @@ function minecraft_modern_scripts() { true ); - // Unsere eigene Slider-Initialisierungs-Datei + // Slider-Init wp_enqueue_script( 'minecraft-modern-slider-script', get_template_directory_uri() . '/js/slider-init.js', - array('swiper-js'), // Hängt von Swiper.js ab - '1.0', + array( 'swiper-js' ), + '1.1', true ); - // NEU: Theme-Toggle-Skript laden + // Theme Toggle wp_enqueue_script( 'theme-toggle-script', get_template_directory_uri() . '/js/theme-toggle.js', - array(), // Keine Abhängigkeiten - '1.0', + array(), + '1.1', true ); - // FAQ Skript laden, wenn der Post-Type aktiv ist - if ( post_type_exists('faq') ) { + // FAQ Skript + if ( post_type_exists( 'faq' ) ) { wp_enqueue_script( 'faq-accordion-script', get_template_directory_uri() . '/js/faq-accordion.js', @@ -103,37 +98,48 @@ function minecraft_modern_scripts() { ); } - // Übergebe ALLE Theme-Einstellungen an das JavaScript + // FIX: 'loop' ergänzt – war in slider-init.js als sliderSettings.loop referenziert, aber nie übergeben wp_localize_script( 'minecraft-modern-slider-script', 'sliderSettings', array( - 'hideArrows' => get_theme_mod( 'slider_hide_arrows', false ) ? '1' : '0', + 'hideArrows' => get_theme_mod( 'slider_hide_arrows', false ) ? '1' : '0', 'hidePagination' => get_theme_mod( 'slider_hide_pagination', false ) ? '1' : '0', 'effect' => get_theme_mod( 'slider_effect', 'fade' ), 'direction' => get_theme_mod( 'slider_direction', 'horizontal' ), 'defaultMode' => get_theme_mod( 'default_theme_mode', 'dark' ), - 'ajax_url' => admin_url('admin-ajax.php') + 'loop' => get_theme_mod( 'slider_loop', true ) ? '1' : '0', + 'ajax_url' => admin_url( 'admin-ajax.php' ), ) ); - // Dies verhindert das Flackern im Customizer. wp_localize_script( - 'minecraft-modern-header-script', // <-- Richtiges Skript-Handle! - 'headerSettings', // <-- Neuer Objektname für Klarheit + 'minecraft-modern-header-script', + 'headerSettings', array( - 'isCustomizer' => is_customize_preview() + 'isCustomizer' => is_customize_preview(), ) ); } add_action( 'wp_enqueue_scripts', 'minecraft_modern_scripts' ); + +// FIX: Scroll-to-Top via Customizer ein-/ausblendbar +function minecraft_modern_scroll_to_top_css() { + if ( ! get_theme_mod( 'show_scroll_to_top', true ) ) { + wp_add_inline_style( 'minecraft-modern-style', '#scroll-to-top { display: none !important; }' ); + } +} +add_action( 'wp_enqueue_scripts', 'minecraft_modern_scroll_to_top_css', 25 ); + + // === Customizer-Datei laden === require get_template_directory() . '/inc/customizer.php'; // === Theme-Updater-Datei laden === require get_template_directory() . '/inc/theme-updater.php'; + // === Footer-Widgets registrieren === function minecraft_modern_footer_widgets() { register_sidebar( array( @@ -168,9 +174,9 @@ function minecraft_modern_footer_widgets() { } add_action( 'widgets_init', 'minecraft_modern_footer_widgets' ); + // === Homepage Sidebar registrieren === function minecraft_modern_homepage_sidebar() { - // Hauptbereich oben register_sidebar( array( 'name' => __( 'Startseiten Sidebar - Oben', 'minecraft-modern-theme' ), 'id' => 'homepage-sidebar-top', @@ -180,8 +186,6 @@ function minecraft_modern_homepage_sidebar() { 'before_title' => '

', 'after_title' => '

', ) ); - - // Mittlerer Bereich 1 register_sidebar( array( 'name' => __( 'Startseiten Sidebar - Mitte 1', 'minecraft-modern-theme' ), 'id' => 'homepage-sidebar-middle-1', @@ -191,8 +195,6 @@ function minecraft_modern_homepage_sidebar() { 'before_title' => '

', 'after_title' => '

', ) ); - - // Mittlerer Bereich 2 register_sidebar( array( 'name' => __( 'Startseiten Sidebar - Mitte 2', 'minecraft-modern-theme' ), 'id' => 'homepage-sidebar-middle-2', @@ -202,19 +204,15 @@ function minecraft_modern_homepage_sidebar() { 'before_title' => '

', 'after_title' => '

', ) ); - - // Unterer Bereich register_sidebar( array( 'name' => __( 'Startseiten Sidebar - Unten', 'minecraft-modern-theme' ), 'id' => 'homepage-sidebar-bottom', - 'description' => __( 'Widget-Bereich unten in der Sidebar (z.B. für Social Media).', 'minecraft-modern-theme' ), + 'description' => __( 'Widget-Bereich unten in der Sidebar.', 'minecraft-modern-theme' ), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', ) ); - - // Zusätzlicher flexibler Bereich register_sidebar( array( 'name' => __( 'Startseiten Sidebar - Extra', 'minecraft-modern-theme' ), 'id' => 'homepage-sidebar-extra', @@ -227,63 +225,80 @@ function minecraft_modern_homepage_sidebar() { } add_action( 'widgets_init', 'minecraft_modern_homepage_sidebar' ); -// === FAQ Custom Post Type & Taxonomy === -function create_faq_post_type() { - // Nur registrieren, wenn im Customizer aktiviert - if ( get_theme_mod( 'faq_enabled', true ) ) { - register_post_type('faq', - array( - 'labels' => 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, // Archiv-Seite /faq/ bleibt als Fallback - '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'); - -// ============================================================================= -// ===== Automatische "Home" Seitenerstellung und Zuweisung (kombiniert) ======= -// ============================================================================= /** - * Erstellt die "Home" Seite und weist sie automatisch als statische Startseite zu, - * wenn das Theme aktiviert wird und noch keine Seite festgelegt ist. + * Rendert alle Sidebar-Sections der Homepage. + * Ersetzt den doppelten Sidebar-Code in front-page.php. */ +function minecraft_modern_render_sidebar_sections() { + $sections = array( + 'homepage-sidebar-top', + 'homepage-sidebar-middle-1', + 'homepage-sidebar-middle-2', + 'homepage-sidebar-bottom', + 'homepage-sidebar-extra', + ); + $classes = array( + 'homepage-sidebar-top' => 'sidebar-top', + 'homepage-sidebar-middle-1' => 'sidebar-middle-1', + 'homepage-sidebar-middle-2' => 'sidebar-middle-2', + 'homepage-sidebar-bottom' => 'sidebar-bottom', + 'homepage-sidebar-extra' => 'sidebar-extra', + ); + foreach ( $sections as $sidebar_id ) { + if ( is_active_sidebar( $sidebar_id ) ) { + $class = isset( $classes[ $sidebar_id ] ) ? ' ' . $classes[ $sidebar_id ] : ''; + echo ''; + } + } +} + + +// === FAQ Custom Post Type & Taxonomy === +function create_faq_post_type() { + if ( get_theme_mod( 'faq_enabled', true ) ) { + register_post_type( 'faq', array( + 'labels' => 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' ); + + +// ============================================================================= +// Automatische "Home" Seitenerstellung +// ============================================================================= + function set_static_front_page_automatically() { - // Nur ausführen, wenn noch keine statische Seite als Startseite festgelegt ist if ( 'page' !== get_option( 'show_on_front' ) ) { - - // Finde die "Home" Seite (oder erstelle sie, falls sie nicht existiert) $home_page = get_page_by_title( 'Home' ); if ( ! $home_page ) { - // Seite erstellen, falls sie nicht existiert $home_page_id = wp_insert_post( array( 'post_title' => 'Home', 'post_content' => 'Diese Seite dient als statische Startseite.', @@ -294,8 +309,6 @@ function set_static_front_page_automatically() { } else { $home_page_id = $home_page->ID; } - - // Setze die Seite als statische Startseite if ( $home_page_id ) { update_option( 'show_on_front', 'page' ); update_option( 'page_on_front', $home_page_id ); @@ -305,12 +318,8 @@ function set_static_front_page_automatically() { add_action( 'after_switch_theme', 'set_static_front_page_automatically' ); -/** - * Fügt eine Body-Klasse hinzu, um den Home-Titel per CSS auszublenden. - */ function add_home_body_class( $classes ) { - // Prüfen, ob wir auf der Startseite sind und die Einstellung zum Ausblenden aktiv ist - if ( is_front_page() && !get_theme_mod( 'show_home_title', true ) ) { + if ( is_front_page() && ! get_theme_mod( 'show_home_title', true ) ) { $classes[] = 'home-title-hidden'; } return $classes; @@ -319,224 +328,216 @@ add_filter( 'body_class', 'add_home_body_class' ); // ============================================================================= -// Automatische FAQ-Seitenerstellung und Template-Zuweisung +// FAQ-Seitenerstellung // ============================================================================= -/** - * Erstellt automatisch eine "FAQ" Seite, wenn die FAQ-Funktion aktiviert wird. - */ function create_faq_page_automatically() { - // Prüfen, ob die FAQ-Funktion aktiv ist - if ( get_theme_mod( 'faq_enabled', true ) ) { - // Prüfen, ob die Seite bereits existiert - if ( get_page_by_title( 'FAQ' ) == null ) { - // Seite erstellen - $new_page = 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, - ); - // Seite in die Datenbank einfügen - wp_insert_post( $new_page ); - } + if ( get_theme_mod( 'faq_enabled', true ) && get_page_by_title( 'FAQ' ) == null ) { + 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, + ) ); } } -// Diese Funktion wird ausgeführt, wenn der Customizer gespeichert wird. add_action( 'customize_save_after', 'create_faq_page_automatically' ); -/** - * Leitet Anfragen für die "FAQ" Seite auf unser spezielles Template um. - */ function load_faq_page_template( $template ) { - // Prüfen, ob die FAQ-Funktion aktiv ist - if ( get_theme_mod( 'faq_enabled', true ) ) { - // Prüfen, ob wir uns auf einer Seite befinden - if ( is_page() ) { - global $post; - // Prüfen, ob der Titel der Seite "FAQ" ist - if ( $post && $post->post_title == 'FAQ' ) { - // Pfad zu unserem Template zurückgeben - return get_template_directory() . '/archive-faq.php'; - } + if ( get_theme_mod( 'faq_enabled', true ) && is_page() ) { + global $post; + if ( $post && $post->post_title === 'FAQ' ) { + return get_template_directory() . '/archive-faq.php'; } } - // Standard-Template in allen anderen Fällen return $template; } add_filter( 'template_include', 'load_faq_page_template' ); // ========================================================================= -// === CUSTOM LOGIN FUNCTIONS ============================================= +// CUSTOM LOGIN FUNCTIONS // ========================================================================= -// Lädt alle notwendigen Styles und Scripts nur für die Login-Seite function minecraft_modern_login_assets() { - // Lade die Login-spezifische CSS - wp_enqueue_style('minecraft-modern-login-style', get_template_directory_uri() . '/css/login-style.css'); - - // Lade Font Awesome für Icons - wp_enqueue_style('font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css'); + wp_enqueue_style( 'minecraft-modern-login-style', get_template_directory_uri() . '/css/login-style.css' ); + wp_enqueue_style( 'font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css' ); - // Lade das JavaScript für den Avatar-Slider - wp_enqueue_script('minecraft-avatar-slider-script', get_template_directory_uri() . '/js/login-slider.js', array('jquery'), '1.0', true); + // FIX: login-slider.js – erster Slide sofort sichtbar (fixiert) + wp_enqueue_script( 'minecraft-avatar-slider-script', get_template_directory_uri() . '/js/login-slider.js', array( 'jquery' ), '1.1', true ); + wp_enqueue_script( 'minecraft-modern-login-script', get_template_directory_uri() . '/js/login-script.js', array( 'jquery' ), '1.0', true ); - // Lade das JavaScript, das die HTML-Struktur anpasst - wp_enqueue_script('minecraft-modern-login-script', get_template_directory_uri() . '/js/login-script.js', array('jquery'), '1.0', true); - - wp_add_inline_script('minecraft-modern-login-script', " + wp_add_inline_script( 'minecraft-modern-login-script', " jQuery(document).ready(function($) { $('.forgetmenot, #nav').wrapAll('
'); }); - "); + " ); - // Übergebe die Slider-Geschwindigkeit aus dem Customizer an das JavaScript - $slider_speed = get_theme_mod('login_avatar_slider_speed', 4); // Standard: 4 Sekunden - wp_localize_script('minecraft-avatar-slider-script', 'avatarSliderSettings', array( - 'speed' => $slider_speed * 1000 // Umwandlung in Millisekunden für JS - )); + $slider_speed = get_theme_mod( 'login_avatar_slider_speed', 4 ); + wp_localize_script( 'minecraft-avatar-slider-script', 'avatarSliderSettings', array( + 'speed' => $slider_speed * 1000, + ) ); - // Hintergrundbild und Logo als Inline-CSS hinzufügen - $login_bg_image = get_theme_mod('login_background_image'); - if ($login_bg_image) { - $custom_css = "body.login { background-image: url('{$login_bg_image}') !important; }"; - wp_add_inline_style('minecraft-modern-login-style', $custom_css); + $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) { - $logo_css = ".login h1 a { background-image: url('{$logo_url}') !important; }"; - wp_add_inline_style('minecraft-modern-login-style', $logo_css); + $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'); +add_action( 'login_enqueue_scripts', 'minecraft_modern_login_assets' ); + -// Erstellt die HTML-Struktur für den Avatar-Slider function add_minecraft_avatar_slider_to_login() { $avatar_html = '
'; $has_avatars = false; - // Durchlaufe alle 5 möglichen Avatar-Plätze - for ($i = 1; $i <= 5; $i++) { - $uuid = get_theme_mod('login_avatar_uuid_' . $i); - if (!empty($uuid)) { - $has_avatars = true; - $avatar_url = "https://visage.surgeplay.com/full/{$uuid}.png"; - // Das erste Bild wird direkt angezeigt - $active_class = ($i === 1) ? 'avatar-slide-active' : ''; - $avatar_html .= 'Minecraft Avatar ' . ($i + 1) . ''; + for ( $i = 1; $i <= 5; $i++ ) { + $uuid = get_theme_mod( 'login_avatar_uuid_' . $i ); + if ( ! empty( $uuid ) ) { + $has_avatars = true; + $avatar_url = 'https://visage.surgeplay.com/full/' . $uuid . '.png'; + // FIX: Klasse wird hier gesetzt, JS überschreibt sie trotzdem (kompatibel) + $active_class = ( $i === 1 ) ? 'avatar-slide avatar-slide-active' : 'avatar-slide'; + $avatar_html .= 'Minecraft Avatar ' . $i . ''; } } $avatar_html .= '
'; - // Nur den Slider ausgeben, wenn mindestens ein Avatar hinterlegt wurde - if ($has_avatars) { + if ( $has_avatars ) { echo $avatar_html; } } -add_action('login_form', 'add_minecraft_avatar_slider_to_login'); +add_action( 'login_form', 'add_minecraft_avatar_slider_to_login' ); + function add_post_login_links() { ?>
- ← Zu + ← Zu
- + '3.0', + '_exported' => date( 'Y-m-d H:i:s' ), + '_theme' => $theme_slug, ); + // 1. Alle Customizer-Einstellungen (Theme Mods) + // Enthält: Farben, Slider, Hero, Social Links, Menü-Design, Login-Einstellungen, Sidebar-Einstellungen usw. + $data['theme_mods'] = get_theme_mods(); + + // 2. Announcement-Bar (gespeichert als wp_options, nicht als Theme Mod) + $announcement_keys = array( + 'mm_announcement_enabled', 'mm_announcement_text', 'mm_announcement_bg', + 'mm_announcement_color', 'mm_announcement_font_size', 'mm_announcement_font_family', + 'mm_announcement_position', 'mm_announcement_countdown_enabled', + 'mm_announcement_countdown_label', 'mm_announcement_countdown_date', + 'mm_announcement_countdown_expired_msg', + ); foreach ( $announcement_keys as $key ) { - $mods[$key] = get_option($key); + $data['announcement'][ $key ] = get_option( $key ); } - // 3. Team Daten holen - $team_data = array(); - $team_query = new WP_Query(array( + // 3. Widget-Konfigurationen aller Theme-Sidebars + $theme_sidebars = array( + 'single-post-sidebar', + 'homepage-sidebar-top', 'homepage-sidebar-middle-1', + 'homepage-sidebar-middle-2', 'homepage-sidebar-bottom', + 'homepage-sidebar-extra', 'footer-1', 'footer-2', 'footer-3', + ); + $all_sidebars = wp_get_sidebars_widgets(); + $widget_data = array(); + foreach ( $theme_sidebars as $sidebar_id ) { + $widget_data[ $sidebar_id ] = array(); + if ( empty( $all_sidebars[ $sidebar_id ] ) ) continue; + foreach ( $all_sidebars[ $sidebar_id ] as $widget_id ) { + if ( ! preg_match( '/^(.+)-(\d+)$/', $widget_id, $m ) ) continue; + $type = $m[1]; + $index = intval( $m[2] ); + $all = get_option( 'widget_' . $type, array() ); + $widget_data[ $sidebar_id ][] = array( + 'type' => $type, + 'index' => $index, + 'settings' => isset( $all[ $index ] ) ? $all[ $index ] : array(), + ); + } + } + $data['widgets'] = $widget_data; + + // 4. Team-Mitglieder + $team_data = array(); + $team_query = new WP_Query( array( 'post_type' => 'team_member', 'posts_per_page' => -1, 'orderby' => 'menu_order', - 'order' => 'ASC' - )); - + 'order' => 'ASC', + ) ); if ( $team_query->have_posts() ) { while ( $team_query->have_posts() ) { $team_query->the_post(); - $team_data[] = array( 'title' => get_the_title(), 'content' => get_the_content(), @@ -544,217 +545,283 @@ function handle_theme_settings_export() { 'menu_order' => get_post_field( 'menu_order', get_the_ID() ), ); } - wp_reset_postdata(); // WICHTIG: Post-Daten zurücksetzen + wp_reset_postdata(); } - - $mods['team_data'] = $team_data; + $data['team'] = $team_data; - // Daten als JSON vorbereiten - $data = json_encode( $mods, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); + // 5. FAQ-Einträge (theme-eigener Custom Post Type) + $faq_data = array(); + $faq_query = new WP_Query( array( + 'post_type' => 'faq', + 'posts_per_page' => -1, + 'orderby' => 'menu_order', + 'order' => 'ASC', + ) ); + if ( $faq_query->have_posts() ) { + while ( $faq_query->have_posts() ) { + $faq_query->the_post(); + $terms = wp_get_post_terms( get_the_ID(), 'faq_category', array( 'fields' => 'names' ) ); + $faq_data[] = array( + 'title' => get_the_title(), + 'content' => get_the_content(), + 'menu_order' => get_post_field( 'menu_order', get_the_ID() ), + 'categories' => is_wp_error( $terms ) ? array() : $terms, + ); + } + wp_reset_postdata(); + } + $data['faqs'] = $faq_data; - // Header für Download setzen + // 6. Custom CSS (Customizer → Zusätzliches CSS) + $data['custom_css'] = wp_get_custom_css(); + + // 7. Menü-Positionen (welches Menü ist welchem Theme-Location zugewiesen) + $data['nav_menu_locations'] = get_theme_mod( 'nav_menu_locations', array() ); + + $json = json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); header( 'Content-Type: application/json; charset=utf-8' ); - header( 'Content-Disposition: attachment; filename=' . $theme_slug . '-settings-' . date( 'Y-m-d' ) . '.json' ); + header( 'Content-Disposition: attachment; filename=' . $theme_slug . '-theme-backup-' . date( 'Y-m-d' ) . '.json' ); header( 'Pragma: no-cache' ); header( 'Expires: 0' ); - - echo $data; + echo $json; exit; } -// 2. Import Handler (AJAX) - ALLE EINSTELLUNGEN + add_action( 'wp_ajax_import_theme_settings', 'handle_theme_settings_import' ); function handle_theme_settings_import() { - // Sicherheitscheck & Nonce if ( ! current_user_can( 'edit_theme_options' ) ) { wp_send_json_error( __( 'Keine Berechtigung.', 'minecraft-modern-theme' ) ); } - check_ajax_referer( 'theme-import-nonce', 'nonce' ); if ( empty( $_FILES['import_file']['tmp_name'] ) ) { wp_send_json_error( __( 'Keine Datei hochgeladen.', 'minecraft-modern-theme' ) ); } - // Datei einlesen - $file = $_FILES['import_file']['tmp_name']; - $json_content = file_get_contents( $file ); - $data = json_decode( $json_content, true ); + $json_content = file_get_contents( $_FILES['import_file']['tmp_name'] ); + $data = json_decode( $json_content, true ); - // JSON validieren if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $data ) ) { - wp_send_json_error( __( 'Die hochgeladene Datei ist keine gültige JSON-Datei.', 'minecraft-modern-theme' ) ); + wp_send_json_error( __( 'Ungültige JSON-Datei.', 'minecraft-modern-theme' ) ); } - // Announcement Keys definieren - $announcement_keys = array( - 'mm_announcement_enabled', - 'mm_announcement_text', - 'mm_announcement_bg', - 'mm_announcement_color', - 'mm_announcement_font_size', - 'mm_announcement_font_family', - 'mm_announcement_position', - 'mm_announcement_countdown_enabled', - 'mm_announcement_countdown_label', - 'mm_announcement_countdown_date', - 'mm_announcement_countdown_expired_msg' - ); + $imported = array(); + $version = isset( $data['_version'] ) ? $data['_version'] : '1.0'; - // KRITISCHER FIX: Team Daten VORHER extrahieren und aus Array entfernen - $team_data = isset($data['team_data']) ? $data['team_data'] : array(); - unset($data['team_data']); // Verhindert Fehler beim Durchlaufen der Theme Mods - - // 1. Theme Mods & Announcement importieren - foreach ( $data as $mod_key => $mod_value ) { - // Unterscheidung: Announcement = Option, Rest = Theme Mod - if ( in_array( $mod_key, $announcement_keys ) ) { - update_option( $mod_key, $mod_value ); - } else { - set_theme_mod( $mod_key, $mod_value ); + // ------------------------------------------------------------------------- + // 1. Customizer / Theme Mods + // ------------------------------------------------------------------------- + $mods = array(); + if ( $version === '3.0' && isset( $data['theme_mods'] ) ) { + $mods = $data['theme_mods']; + } elseif ( $version === '2.0' && isset( $data['theme_mods'] ) ) { + $mods = $data['theme_mods']; + } else { + // Altes v1-Format: alles auf oberster Ebene + $skip = array( '_version', '_exported', '_theme', 'announcement', 'widgets', 'team', 'faqs', 'menus', 'wp_options', 'custom_css', 'team_data' ); + foreach ( $data as $k => $v ) { + if ( ! in_array( $k, $skip ) ) $mods[ $k ] = $v; } } + foreach ( $mods as $key => $value ) { + set_theme_mod( $key, $value ); + } + $imported[] = 'Customizer-Einstellungen'; - // 2. Team Daten importieren - if ( ! empty( $team_data ) ) { - - // Vorherige Team-Mitglieder löschen (Clean Import) - $existing_team = new WP_Query(array( - 'post_type' => 'team_member', - 'posts_per_page' => -1, - 'fields' => 'ids' - )); - - if ( $existing_team->have_posts() ) { - foreach ( $existing_team->posts as $post_id ) { - wp_delete_post( $post_id, true ); // true = permanent löschen + // ------------------------------------------------------------------------- + // 2. Announcement-Bar + // ------------------------------------------------------------------------- + $announcement_keys = array( + 'mm_announcement_enabled', 'mm_announcement_text', 'mm_announcement_bg', + 'mm_announcement_color', 'mm_announcement_font_size', 'mm_announcement_font_family', + 'mm_announcement_position', 'mm_announcement_countdown_enabled', + 'mm_announcement_countdown_label', 'mm_announcement_countdown_date', + 'mm_announcement_countdown_expired_msg', + ); + $ann = isset( $data['announcement'] ) ? $data['announcement'] : $data; + foreach ( $announcement_keys as $key ) { + if ( array_key_exists( $key, $ann ) ) { + update_option( $key, $ann[ $key ] ); + } + } + $imported[] = 'Ankündigung'; + + // ------------------------------------------------------------------------- + // 3. Widgets + // ------------------------------------------------------------------------- + if ( ! empty( $data['widgets'] ) ) { + $current_sidebars = get_option( 'sidebars_widgets', array() ); + foreach ( $data['widgets'] as $sidebar_id => $widgets ) { + $current_sidebars[ $sidebar_id ] = array(); + foreach ( $widgets as $widget ) { + $type = sanitize_key( $widget['type'] ); + $index = intval( $widget['index'] ); + $all = get_option( 'widget_' . $type, array() ); + $all[ $index ] = $widget['settings']; + update_option( 'widget_' . $type, $all ); + $current_sidebars[ $sidebar_id ][] = $type . '-' . $index; } } - wp_reset_postdata(); // WICHTIG: Post-Daten zurücksetzen + update_option( 'sidebars_widgets', $current_sidebars ); + $imported[] = 'Widgets'; + } - // Neue Mitglieder anlegen + // ------------------------------------------------------------------------- + // 4. Team-Mitglieder + // ------------------------------------------------------------------------- + $team_data = isset( $data['team'] ) ? $data['team'] : ( isset( $data['team_data'] ) ? $data['team_data'] : array() ); + if ( ! empty( $team_data ) ) { + $existing = new WP_Query( array( 'post_type' => 'team_member', 'posts_per_page' => -1, 'fields' => 'ids' ) ); + if ( $existing->have_posts() ) { + foreach ( $existing->posts as $pid ) wp_delete_post( $pid, true ); + } + wp_reset_postdata(); foreach ( $team_data as $member ) { - $new_id = wp_insert_post(array( + $id = wp_insert_post( array( 'post_title' => sanitize_text_field( $member['title'] ), - 'post_content' => sanitize_textarea_field( $member['content'] ), + 'post_content' => wp_kses_post( $member['content'] ), 'post_type' => 'team_member', 'post_status' => 'publish', - 'menu_order' => isset( $member['menu_order'] ) ? intval( $member['menu_order'] ) : 0 - )); + 'menu_order' => intval( isset( $member['menu_order'] ) ? $member['menu_order'] : 0 ), + ) ); + if ( $id && ! is_wp_error( $id ) && ! empty( $member['rank'] ) ) { + update_post_meta( $id, '_team_member_rank', sanitize_text_field( $member['rank'] ) ); + } + } + $imported[] = count( $team_data ) . ' Team-Mitglieder'; + } - if ( $new_id && ! is_wp_error( $new_id ) ) { - // Rang als Meta-Data speichern - if ( isset( $member['rank'] ) ) { - update_post_meta( $new_id, '_team_member_rank', sanitize_text_field( $member['rank'] ) ); + // ------------------------------------------------------------------------- + // 5. FAQs + // ------------------------------------------------------------------------- + if ( ! empty( $data['faqs'] ) ) { + $existing = new WP_Query( array( 'post_type' => 'faq', 'posts_per_page' => -1, 'fields' => 'ids' ) ); + if ( $existing->have_posts() ) { + foreach ( $existing->posts as $pid ) wp_delete_post( $pid, true ); + } + wp_reset_postdata(); + foreach ( $data['faqs'] as $faq ) { + $id = wp_insert_post( array( + 'post_title' => sanitize_text_field( $faq['title'] ), + 'post_content' => wp_kses_post( $faq['content'] ), + 'post_type' => 'faq', + 'post_status' => 'publish', + 'menu_order' => intval( isset( $faq['menu_order'] ) ? $faq['menu_order'] : 0 ), + ) ); + if ( $id && ! is_wp_error( $id ) && ! empty( $faq['categories'] ) ) { + foreach ( (array) $faq['categories'] as $cat_name ) { + $term = term_exists( sanitize_text_field( $cat_name ), 'faq_category' ); + if ( ! $term ) { + $term = wp_insert_term( sanitize_text_field( $cat_name ), 'faq_category' ); + } + if ( ! is_wp_error( $term ) ) { + wp_set_post_terms( $id, array( intval( $term['term_id'] ) ), 'faq_category', true ); + } } } } + $imported[] = count( $data['faqs'] ) . ' FAQs'; } - wp_send_json_success( __( 'Einstellungen und Team erfolgreich importiert! Bilder müssen ggf. neu hochgeladen werden.', 'minecraft-modern-theme' ) ); + // ------------------------------------------------------------------------- + // 6. Custom CSS + // ------------------------------------------------------------------------- + if ( isset( $data['custom_css'] ) && $data['custom_css'] !== '' ) { + wp_update_custom_css_post( $data['custom_css'] ); + $imported[] = 'Custom CSS'; + } + + // ------------------------------------------------------------------------- + // 7. Menü-Positionen + // ------------------------------------------------------------------------- + if ( ! empty( $data['nav_menu_locations'] ) ) { + set_theme_mod( 'nav_menu_locations', $data['nav_menu_locations'] ); + $imported[] = 'Menü-Positionen'; + } + + wp_send_json_success( sprintf( + __( 'Erfolgreich wiederhergestellt: %s', 'minecraft-modern-theme' ), + implode( ', ', $imported ) + ) ); } -/* - * ------------------------------------------------------------------------- - * Announcement Bar (Admin + Frontend) – vollständiges Modul mit Font-Vorschau & Countdown - * ------------------------------------------------------------------------- - */ -/** - * Liste verfügbarer Fonts (Label, CSS-Family, Google-Flag, Google-Name) - */ +// ========================================================================= +// ANNOUNCEMENT BAR +// ========================================================================= + function mm_announcement_get_font_list() { return array( - 'inherit' => array('label' => 'Theme-Standard', 'css' => 'inherit', 'google' => false, 'google_name' => ''), - 'Arial' => array('label' => 'Arial', 'css' => 'Arial, Helvetica, sans-serif', 'google' => false, 'google_name' => ''), - 'Roboto' => array('label' => 'Roboto', 'css' => "'Roboto', sans-serif", 'google' => true, 'google_name' => 'Roboto'), - 'Montserrat' => array('label' => 'Montserrat', 'css' => "'Montserrat', sans-serif", 'google' => true, 'google_name' => 'Montserrat'), - 'Open Sans' => array('label' => 'Open Sans', 'css' => "'Open Sans', sans-serif", 'google' => true, 'google_name' => 'Open+Sans'), - 'Lato' => array('label' => 'Lato', 'css' => "'Lato', sans-serif", 'google' => true, 'google_name' => 'Lato'), - 'Poppins' => array('label' => 'Poppins', 'css' => "'Poppins', sans-serif", 'google' => true, 'google_name' => 'Poppins'), - 'Source Sans Pro' => array('label' => 'Source Sans Pro', 'css' => "'Source Sans Pro', sans-serif", 'google' => true, 'google_name' => 'Source+Sans+Pro'), - 'Noto Sans' => array('label' => 'Noto Sans', 'css' => "'Noto Sans', sans-serif", 'google' => true, 'google_name' => 'Noto+Sans'), - 'Raleway' => array('label' => 'Raleway', 'css' => "'Raleway', sans-serif", 'google' => true, 'google_name' => 'Raleway'), - 'Merriweather' => array('label' => 'Merriweather', 'css' => "'Merriweather', serif", 'google' => true, 'google_name' => 'Merriweather'), - 'Playfair Display' => array('label' => 'Playfair Display', 'css' => "'Playfair Display', serif", 'google' => true, 'google_name' => 'Playfair+Display'), - 'Oswald' => array('label' => 'Oswald', 'css' => "'Oswald', sans-serif", 'google' => true, 'google_name' => 'Oswald'), - 'Rubik' => array('label' => 'Rubik', 'css' => "'Rubik', sans-serif", 'google' => true, 'google_name' => 'Rubik'), - 'Inter' => array('label' => 'Inter', 'css' => "'Inter', sans-serif", 'google' => true, 'google_name' => 'Inter'), - 'Nunito' => array('label' => 'Nunito', 'css' => "'Nunito', sans-serif", 'google' => true, 'google_name' => 'Nunito'), - 'Ubuntu' => array('label' => 'Ubuntu', 'css' => "'Ubuntu', sans-serif", 'google' => true, 'google_name' => 'Ubuntu'), - 'PT Sans' => array('label' => 'PT Sans', 'css' => "'PT Sans', sans-serif", 'google' => true, 'google_name' => 'PT+Sans'), - 'Archivo' => array('label' => 'Archivo', 'css' => "'Archivo', sans-serif", 'google' => true, 'google_name' => 'Archivo'), - 'Fira Sans' => array('label' => 'Fira Sans', 'css' => "'Fira Sans', sans-serif", 'google' => true, 'google_name' => 'Fira+Sans'), - 'Work Sans' => array('label' => 'Work Sans', 'css' => "'Work Sans', sans-serif", 'google' => true, 'google_name' => 'Work+Sans'), - 'Quicksand' => array('label' => 'Quicksand', 'css' => "'Quicksand', sans-serif", 'google' => true, 'google_name' => 'Quicksand'), - 'Karla' => array('label' => 'Karla', 'css' => "'Karla', sans-serif", 'google' => true, 'google_name' => 'Karla'), - - // Script / Schreibschrift - 'Dancing Script' => array('label' => 'Dancing Script', 'css' => "'Dancing Script', cursive", 'google' => true, 'google_name' => 'Dancing+Script'), - 'Pacifico' => array('label' => 'Pacifico', 'css' => "'Pacifico', cursive", 'google' => true, 'google_name' => 'Pacifico'), - 'Great Vibes' => array('label' => 'Great Vibes', 'css' => "'Great Vibes', cursive", 'google' => true, 'google_name' => 'Great+Vibes'), - 'Satisfy' => array('label' => 'Satisfy', 'css' => "'Satisfy', cursive", 'google' => true, 'google_name' => 'Satisfy'), - 'Allura' => array('label' => 'Allura', 'css' => "'Allura', cursive", 'google' => true, 'google_name' => 'Allura'), - 'Alex Brush' => array('label' => 'Alex Brush', 'css' => "'Alex Brush', cursive", 'google' => true, 'google_name' => 'Alex+Brush'), - 'Cookie' => array('label' => 'Cookie', 'css' => "'Cookie', cursive", 'google' => true, 'google_name' => 'Cookie'), + 'inherit' => array( 'label' => 'Theme-Standard', 'css' => 'inherit', 'google' => false, 'google_name' => '' ), + 'Arial' => array( 'label' => 'Arial', 'css' => 'Arial, Helvetica, sans-serif', 'google' => false, 'google_name' => '' ), + 'Roboto' => array( 'label' => 'Roboto', 'css' => "'Roboto', sans-serif", 'google' => true, 'google_name' => 'Roboto' ), + 'Montserrat' => array( 'label' => 'Montserrat', 'css' => "'Montserrat', sans-serif", 'google' => true, 'google_name' => 'Montserrat' ), + 'Open Sans' => array( 'label' => 'Open Sans', 'css' => "'Open Sans', sans-serif", 'google' => true, 'google_name' => 'Open+Sans' ), + 'Lato' => array( 'label' => 'Lato', 'css' => "'Lato', sans-serif", 'google' => true, 'google_name' => 'Lato' ), + 'Poppins' => array( 'label' => 'Poppins', 'css' => "'Poppins', sans-serif", 'google' => true, 'google_name' => 'Poppins' ), + 'Source Sans Pro' => array( 'label' => 'Source Sans Pro', 'css' => "'Source Sans Pro', sans-serif", 'google' => true, 'google_name' => 'Source+Sans+Pro' ), + 'Noto Sans' => array( 'label' => 'Noto Sans', 'css' => "'Noto Sans', sans-serif", 'google' => true, 'google_name' => 'Noto+Sans' ), + 'Raleway' => array( 'label' => 'Raleway', 'css' => "'Raleway', sans-serif", 'google' => true, 'google_name' => 'Raleway' ), + 'Merriweather' => array( 'label' => 'Merriweather', 'css' => "'Merriweather', serif", 'google' => true, 'google_name' => 'Merriweather' ), + 'Playfair Display' => array( 'label' => 'Playfair Display', 'css' => "'Playfair Display', serif", 'google' => true, 'google_name' => 'Playfair+Display' ), + 'Oswald' => array( 'label' => 'Oswald', 'css' => "'Oswald', sans-serif", 'google' => true, 'google_name' => 'Oswald' ), + 'Rubik' => array( 'label' => 'Rubik', 'css' => "'Rubik', sans-serif", 'google' => true, 'google_name' => 'Rubik' ), + 'Inter' => array( 'label' => 'Inter', 'css' => "'Inter', sans-serif", 'google' => true, 'google_name' => 'Inter' ), + 'Nunito' => array( 'label' => 'Nunito', 'css' => "'Nunito', sans-serif", 'google' => true, 'google_name' => 'Nunito' ), + 'Ubuntu' => array( 'label' => 'Ubuntu', 'css' => "'Ubuntu', sans-serif", 'google' => true, 'google_name' => 'Ubuntu' ), + 'PT Sans' => array( 'label' => 'PT Sans', 'css' => "'PT Sans', sans-serif", 'google' => true, 'google_name' => 'PT+Sans' ), + 'Archivo' => array( 'label' => 'Archivo', 'css' => "'Archivo', sans-serif", 'google' => true, 'google_name' => 'Archivo' ), + 'Fira Sans' => array( 'label' => 'Fira Sans', 'css' => "'Fira Sans', sans-serif", 'google' => true, 'google_name' => 'Fira+Sans' ), + 'Work Sans' => array( 'label' => 'Work Sans', 'css' => "'Work Sans', sans-serif", 'google' => true, 'google_name' => 'Work+Sans' ), + 'Quicksand' => array( 'label' => 'Quicksand', 'css' => "'Quicksand', sans-serif", 'google' => true, 'google_name' => 'Quicksand' ), + 'Karla' => array( 'label' => 'Karla', 'css' => "'Karla', sans-serif", 'google' => true, 'google_name' => 'Karla' ), + 'Dancing Script' => array( 'label' => 'Dancing Script', 'css' => "'Dancing Script', cursive", 'google' => true, 'google_name' => 'Dancing+Script' ), + 'Pacifico' => array( 'label' => 'Pacifico', 'css' => "'Pacifico', cursive", 'google' => true, 'google_name' => 'Pacifico' ), + 'Great Vibes' => array( 'label' => 'Great Vibes', 'css' => "'Great Vibes', cursive", 'google' => true, 'google_name' => 'Great+Vibes' ), + 'Satisfy' => array( 'label' => 'Satisfy', 'css' => "'Satisfy', cursive", 'google' => true, 'google_name' => 'Satisfy' ), + 'Allura' => array( 'label' => 'Allura', 'css' => "'Allura', cursive", 'google' => true, 'google_name' => 'Allura' ), + 'Alex Brush' => array( 'label' => 'Alex Brush', 'css' => "'Alex Brush', cursive", 'google' => true, 'google_name' => 'Alex+Brush' ), + 'Cookie' => array( 'label' => 'Cookie', 'css' => "'Cookie', cursive", 'google' => true, 'google_name' => 'Cookie' ), ); } - -/* ------------------ Admin: Einstellungen & Menü ------------------ */ function mm_announcement_admin_init() { - add_menu_page( - 'Ankündigung', - 'Ankündigung', - 'manage_options', - 'mm-announcement', - 'mm_announcement_admin_page', - 'dashicons-megaphone', - 61 - ); + add_menu_page( 'Ankündigung', 'Ankündigung', 'manage_options', 'mm-announcement', 'mm_announcement_admin_page', 'dashicons-megaphone', 61 ); - register_setting('mm_announcement_group', 'mm_announcement_enabled'); - register_setting('mm_announcement_group', 'mm_announcement_text'); - register_setting('mm_announcement_group', 'mm_announcement_bg'); - register_setting('mm_announcement_group', 'mm_announcement_color'); - register_setting('mm_announcement_group', 'mm_announcement_font_size'); - register_setting('mm_announcement_group', 'mm_announcement_font_family'); - register_setting('mm_announcement_group', 'mm_announcement_position'); - - // --- NEU: Countdown Timer Settings --- - register_setting('mm_announcement_group', 'mm_announcement_countdown_enabled'); - register_setting('mm_announcement_group', 'mm_announcement_countdown_label'); - register_setting('mm_announcement_group', 'mm_announcement_countdown_date'); - register_setting('mm_announcement_group', 'mm_announcement_countdown_expired_msg'); + register_setting( 'mm_announcement_group', 'mm_announcement_enabled' ); + register_setting( 'mm_announcement_group', 'mm_announcement_text' ); + register_setting( 'mm_announcement_group', 'mm_announcement_bg' ); + register_setting( 'mm_announcement_group', 'mm_announcement_color' ); + register_setting( 'mm_announcement_group', 'mm_announcement_font_size' ); + register_setting( 'mm_announcement_group', 'mm_announcement_font_family' ); + register_setting( 'mm_announcement_group', 'mm_announcement_position' ); + register_setting( 'mm_announcement_group', 'mm_announcement_countdown_enabled' ); + register_setting( 'mm_announcement_group', 'mm_announcement_countdown_label' ); + register_setting( 'mm_announcement_group', 'mm_announcement_countdown_date' ); + register_setting( 'mm_announcement_group', 'mm_announcement_countdown_expired_msg' ); } -add_action('admin_menu', 'mm_announcement_admin_init'); +add_action( 'admin_menu', 'mm_announcement_admin_init' ); -/* ------------------ Admin: Seite (mit Font-Select & Vorschau) ------------------ */ function mm_announcement_admin_page() { - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - - $fonts = mm_announcement_get_font_list(); - $selected_font = get_option('mm_announcement_font_family', 'inherit'); - $selected_size = (int) get_option('mm_announcement_font_size', 16 ); - $bg = esc_attr( get_option('mm_announcement_bg', '#1e1e1e') ); - $color = esc_attr( get_option('mm_announcement_color', '#ffffff') ); - $text_sample = wp_strip_all_tags( get_option('mm_announcement_text') ) ?: 'Das ist eine Vorschau: Wie sieht die Schrift aus?'; + if ( ! current_user_can( 'manage_options' ) ) return; + $fonts = mm_announcement_get_font_list(); + $selected_font = get_option( 'mm_announcement_font_family', 'inherit' ); + $selected_size = (int) get_option( 'mm_announcement_font_size', 16 ); + $bg = esc_attr( get_option( 'mm_announcement_bg', '#1e1e1e' ) ); + $color = esc_attr( get_option( 'mm_announcement_color', '#ffffff' ) ); + $text_sample = wp_strip_all_tags( get_option( 'mm_announcement_text' ) ) ?: 'Das ist eine Vorschau: Wie sieht die Schrift aus?'; ?>

Header-Ankündigung

- -

- Diese Leiste wird auf allen Seiten angezeigt. Die Vorschau unten zeigt sofort, wie die Ankündigung aussieht — Änderungen im Editor oder an den Design-Feldern wirken direkt in der Vorschau, erst wenn du auf Änderungen speichern klickst, werden die Einstellungen im Frontend übernommen. -

+

Diese Leiste wird auf allen Seiten angezeigt. Die Vorschau unten zeigt sofort, wie die Ankündigung aussieht — Änderungen wirken direkt in der Vorschau, erst nach Änderungen speichern werden sie im Frontend übernommen.

- +

Allgemein

@@ -762,10 +829,9 @@ function mm_announcement_admin_page() {
Aktivieren -

Wenn deaktiviert, wird die Leiste nicht angezeigt.

@@ -773,96 +839,44 @@ function mm_announcement_admin_page() {

Inhalt

- +
TextText - 6, - 'media_buttons' => false, - 'tinymce' => true, - 'quicktags' => true, - ) - ); - ?> + 6, 'media_buttons' => false, 'tinymce' => true, 'quicktags' => true ) ); ?> - - -

Verfügbare Icons

-

Diese Icons kannst du direkt im Ankündigungstext verwenden. Klicke auf ein Icon, um es in den Editor einzufügen.

- -
+

Klicke auf ein Icon, um es in den Editor einzufügen.

+
'.$icon.''; + $icons = array( '⚡', '‼️', '❗', '✅', '❌', '⭐', '🔥', '💡', '📢', '🎮', '🏆', '🔔', '🎉', '💬', '🛡️' ); + foreach ( $icons as $icon ) { + echo ''; } ?>
- - +

HTML erlaubt (z. B. <a>-Links).

-

HTML erlaubt (z. B. <a>-Links). Änderungen hier erscheinen sofort in der Vorschau — sie werden aber erst nach "Änderungen speichern" im Frontend übernommen.

- - -
-
- +
+
+
- -

- Live Vorschau -

+

Live Vorschau

-
@@ -873,10 +887,9 @@ function mm_announcement_admin_page() { Anzeigeort -

Wähle die Position für die Anzeige. Die Vorschau zeigt die Position optisch — tatsächliche Frontend-Platzierung erfolgt nach Speichern.

@@ -900,153 +913,98 @@ function mm_announcement_admin_page() { -

Wähle eine Schriftart. Die Vorschau lädt Google-Fonts automatisch für die Vorschau an (nur im Admin).

-

Countdown Timer

- + - - + + - + - +
Countdown aktivieren - -

Zeigt einen Countdown neben dem Ankündigungstext an.

-
Label (Text vor dem Timer) - -

z.B. "Server Restart in:"

-
Label (Text vor Timer)
Zieldatum & Uhrzeit - -

Wähle das Datum und die Uhrzeit (lokale Server-Zeit).

-
Nachricht nach Ablauf - -

Text, der angezeigt wird, wenn der Countdown bei 0 ist.

-
- +
-
- + if ( $countdown_enabled && ! empty( $countdown_date ) ) { + $countdown_html = '
' . $countdown_label . ' Laden...
'; } - ?>
+ data-position="" + style="background:;color:;font-size:px;font-family:;">
-
+
- +
get_option('mm_announcement_font_family', 'inherit'), - 'size' => (int) get_option('mm_announcement_font_size', 16), - 'bg' => get_option('mm_announcement_bg', '#1e1e1e'), - 'color'=> get_option('mm_announcement_color', '#ffffff'), - 'text' => wp_kses_post( get_option('mm_announcement_text') ) - ); - wp_localize_script( 'mm-announcement-admin-script', 'MM_Announcement_Current', $current ); + wp_enqueue_script( 'mm-announcement-admin-script', get_template_directory_uri() . '/js/mm-announcement-admin.js', array( 'jquery' ), '1.1', true ); + wp_localize_script( 'mm-announcement-admin-script', 'MM_Announcement_Fonts', mm_announcement_get_font_list() ); + wp_localize_script( 'mm-announcement-admin-script', 'MM_Announcement_Current', array( + 'font' => get_option( 'mm_announcement_font_family', 'inherit' ), + 'size' => (int) get_option( 'mm_announcement_font_size', 16 ), + 'bg' => get_option( 'mm_announcement_bg', '#1e1e1e' ), + 'color' => get_option( 'mm_announcement_color', '#ffffff' ), + 'text' => wp_kses_post( get_option( 'mm_announcement_text' ) ), + ) ); } add_action( 'admin_enqueue_scripts', 'mm_announcement_admin_assets' ); -/* ------------------------------------------------------------------------- - * COMPLETES TEAM MODUL (SICHER & FUNKTIONIEREND) - * ------------------------------------------------------------------------- */ +// ========================================================================= +// TEAM MODUL +// ========================================================================= -// === 1. Custom Post Type Registrierung === function create_team_post_type() { - // Nur laden, wenn im Customizer aktiviert if ( get_theme_mod( 'team_enabled', true ) ) { - register_post_type('team_member', - array( - 'labels' => array( - 'name' => __( 'Team', 'minecraft-modern-theme' ), - 'singular_name' => __( 'Teammitglied', 'minecraft-modern-theme' ), - 'add_new' => __( 'Neues Mitglied', 'minecraft-modern-theme' ), - 'menu_name' => __( 'Team', 'minecraft-modern-theme' ), - ), - 'public' => true, - 'has_archive' => true, - 'menu_icon' => 'dashicons-groups', - 'supports' => array( 'title', 'thumbnail', 'page-attributes' ), - 'rewrite' => array( 'slug' => 'team' ), - 'show_in_rest' => true, - - // FIX: Standard-Menü ausblenden, wir nutzen nur den Manager - 'show_in_menu' => false, - - ) - ); + register_post_type( 'team_member', array( + 'labels' => array( + 'name' => __( 'Team', 'minecraft-modern-theme' ), + 'singular_name' => __( 'Teammitglied', 'minecraft-modern-theme' ), + 'add_new' => __( 'Neues Mitglied', 'minecraft-modern-theme' ), + 'menu_name' => __( 'Team', 'minecraft-modern-theme' ), + ), + 'public' => true, + 'has_archive' => true, + 'menu_icon' => 'dashicons-groups', + 'supports' => array( 'title', 'thumbnail', 'page-attributes' ), + 'rewrite' => array( 'slug' => 'team' ), + 'show_in_rest' => true, + 'show_in_menu' => false, + ) ); } } -add_action('init', 'create_team_post_type'); +add_action( 'init', 'create_team_post_type' ); + -// === 2. Meta-Box für Rang === function add_team_meta_boxes() { - add_meta_box( - 'team_member_rank_box', - __( 'Rang & Position', 'minecraft-modern-theme' ), - 'team_member_rank_callback', - 'team_member', - 'side', - 'default' - ); + add_meta_box( 'team_member_rank_box', __( 'Rang & Position', 'minecraft-modern-theme' ), 'team_member_rank_callback', 'team_member', 'side', 'default' ); } -add_action('add_meta_boxes', 'add_team_meta_boxes'); +add_action( 'add_meta_boxes', 'add_team_meta_boxes' ); function team_member_rank_callback( $post ) { wp_nonce_field( 'team_member_rank_save', 'team_member_rank_nonce' ); @@ -1137,114 +1073,163 @@ function save_team_member_rank( $post_id ) { if ( ! wp_verify_nonce( $_POST['team_member_rank_nonce'], 'team_member_rank_save' ) ) return; if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return; if ( ! current_user_can( 'edit_post', $post_id ) ) return; - if ( isset( $_POST['team_member_rank'] ) ) { update_post_meta( $post_id, '_team_member_rank', sanitize_text_field( $_POST['team_member_rank'] ) ); } } add_action( 'save_post', 'save_team_member_rank' ); -// === 3. Team Manager Admin Page === -add_action('admin_menu', 'register_team_manager_page'); + +add_action( 'admin_menu', 'register_team_manager_page' ); function register_team_manager_page() { - add_menu_page( - 'Team Manager', - 'Team Manager', - 'manage_options', - 'mm-team-manager', - 'mm_team_manager_page_html', - 'dashicons-groups', - 6 - ); - - // FIX: Media Uploader Skript laden - add_action('admin_enqueue_scripts', function($hook) { - if ($hook === 'toplevel_page_mm-team-manager') { + add_menu_page( 'Team Manager', 'Team Manager', 'manage_options', 'mm-team-manager', 'mm_team_manager_page_html', 'dashicons-groups', 6 ); + add_action( 'admin_enqueue_scripts', function( $hook ) { + if ( $hook === 'toplevel_page_mm-team-manager' ) { wp_enqueue_media(); } - }); + } ); } +// Breite-Fix nur auf der Team-Manager-Seite +function mm_team_manager_admin_css() { + $screen = get_current_screen(); + if ( ! $screen || $screen->id !== 'toplevel_page_mm-team-manager' ) return; + echo ''; +} +add_action( 'admin_head', 'mm_team_manager_admin_css' ); + function mm_team_manager_page_html() { ?> -
+

Team Verwaltung

Hier kannst du Teammitglieder hinzufügen, sortieren und bearbeiten.

- -
+

Neues Mitglied hinzufügen

-
- +

- +
-

- +
- -
+

- +
-
-
-
- - - Kein Bild gewählt +
+ +
+
+ +

UUID eingeben → Avatar wird automatisch geladen

+
+ +
+
+
+ + + Kein Bild gewählt +
+

Wird ignoriert wenn UUID gesetzt ist

+
+ +
+
+
+ + + Kein Banner gewählt +
+

Hintergrundbild der Card (optional)

+
+
+ +
+
+
+ +
-
-
- +
+
- -
- +
+
- - - + + + - - + + + 'team_member', 'posts_per_page' => -1, 'orderby' => 'menu_order', 'order' => 'ASC')); - if ($team_query->have_posts()) : - while ($team_query->have_posts()) : $team_query->the_post(); - $id = get_the_ID(); - $name = get_the_title(); - $rank = get_post_meta($id, '_team_member_rank', true); - $bio = get_the_content(); - $img_id = get_post_thumbnail_id($id); + $team_query = new WP_Query( array( 'post_type' => 'team_member', 'posts_per_page' => -1, 'orderby' => 'menu_order', 'order' => 'ASC' ) ); + if ( $team_query->have_posts() ) : + while ( $team_query->have_posts() ) : $team_query->the_post(); + $id = get_the_ID(); + $name = get_the_title(); + $rank = get_post_meta( $id, '_team_member_rank', true ); + $bio = get_the_content(); + $uuid = get_post_meta( $id, '_team_member_uuid', true ); + $img_id = get_post_thumbnail_id( $id ); + $banner_id = get_post_meta( $id, '_team_member_banner', true ); + $banner_url = $banner_id ? wp_get_attachment_image_url( $banner_id, 'medium' ) : false; + + // Avatar anzeigen: UUID > Bild > Placeholder + if ( $uuid ) { + $avatar_src = 'https://visage.surgeplay.com/bust/' . esc_attr($uuid) . '.png'; + } elseif ( $img_id ) { + $avatar_src = wp_get_attachment_image_url( $img_id, array(40,40) ); + } else { + $avatar_src = false; + } ?> - - - - - + + + + - @@ -1252,7 +1237,7 @@ function mm_team_manager_page_html() { '; + echo ''; endif; ?> @@ -1260,123 +1245,214 @@ function mm_team_manager_page_html() { - - - - sanitize_text_field($_POST['name']), - 'post_content' => sanitize_textarea_field($_POST['bio']), - 'post_type' => 'team_member', 'post_status' => 'publish', 'menu_order' => 999 - )); - if ($id && !is_wp_error($id)) { - update_post_meta($id, '_team_member_rank', sanitize_text_field($_POST['rank'])); - if (!empty($_POST['img_id'])) set_post_thumbnail($id, intval($_POST['img_id'])); - wp_send_json_success('Hinzugefügt'); - } else { wp_send_json_error('Fehler'); } + check_ajax_referer( 'mm_team_nonce', 'nonce' ); + if ( ! current_user_can( 'publish_posts' ) ) wp_send_json_error( 'Keine Berechtigung' ); + + $id = wp_insert_post( array( + 'post_title' => sanitize_text_field( $_POST['name'] ), + 'post_content' => sanitize_textarea_field( $_POST['bio'] ), + 'post_type' => 'team_member', + 'post_status' => 'publish', + 'menu_order' => 999, + ) ); + + if ( ! $id || is_wp_error( $id ) ) { + wp_send_json_error( 'Fehler beim Erstellen' ); + } + + update_post_meta( $id, '_team_member_rank', sanitize_text_field( $_POST['rank'] ) ); + + // UUID speichern (kein externer Request hier – nur als Text speichern) + if ( ! empty( $_POST['uuid'] ) ) { + $uuid = sanitize_text_field( trim( $_POST['uuid'] ) ); + update_post_meta( $id, '_team_member_uuid', $uuid ); + } elseif ( ! empty( $_POST['img_id'] ) ) { + set_post_thumbnail( $id, intval( $_POST['img_id'] ) ); + } + + // Banner-Bild speichern + if ( ! empty( $_POST['banner_id'] ) ) { + update_post_meta( $id, '_team_member_banner', intval( $_POST['banner_id'] ) ); + } + + wp_send_json_success( array( 'id' => $id, 'msg' => 'Hinzugefügt' ) ); } -add_action('wp_ajax_mm_update_team_member', 'handle_mm_update_team_member'); +add_action( 'wp_ajax_mm_update_team_member', 'handle_mm_update_team_member' ); function handle_mm_update_team_member() { - check_ajax_referer('mm_team_nonce', 'nonce'); - if (!current_user_can('edit_posts')) wp_send_json_error('Keine Berechtigung'); - $id = intval($_POST['id']); - wp_update_post(array('ID' => $id, 'post_title' => sanitize_text_field($_POST['title']), 'post_content' => sanitize_textarea_field($_POST['bio']))); - update_post_meta($id, '_team_member_rank', sanitize_text_field($_POST['rank'])); - wp_send_json_success('Gespeichert'); + check_ajax_referer( 'mm_team_nonce', 'nonce' ); + if ( ! current_user_can( 'edit_posts' ) ) wp_send_json_error( 'Keine Berechtigung' ); + $id = intval( $_POST['id'] ); + wp_update_post( array( + 'ID' => $id, + 'post_title' => sanitize_text_field( $_POST['title'] ), + 'post_content' => sanitize_textarea_field( $_POST['bio'] ), + ) ); + update_post_meta( $id, '_team_member_rank', sanitize_text_field( $_POST['rank'] ) ); + // UUID speichern oder löschen + if ( isset( $_POST['uuid'] ) ) { + $uuid = sanitize_text_field( trim( $_POST['uuid'] ) ); + if ( $uuid ) { + update_post_meta( $id, '_team_member_uuid', $uuid ); + } else { + delete_post_meta( $id, '_team_member_uuid' ); + } + } + // Bild nur setzen wenn keine UUID + if ( empty( $_POST['uuid'] ) && ! empty( $_POST['img_id'] ) ) { + set_post_thumbnail( $id, intval( $_POST['img_id'] ) ); + } + // Banner speichern + if ( isset( $_POST['banner_id'] ) ) { + if ( ! empty( $_POST['banner_id'] ) ) { + update_post_meta( $id, '_team_member_banner', intval( $_POST['banner_id'] ) ); + } + } + wp_send_json_success( 'Gespeichert' ); } -add_action('wp_ajax_mm_delete_team_member', 'handle_mm_delete_team_member'); +add_action( 'wp_ajax_mm_delete_team_member', 'handle_mm_delete_team_member' ); function handle_mm_delete_team_member() { - check_ajax_referer('mm_team_nonce', 'nonce'); - if (!current_user_can('delete_posts')) wp_send_json_error('Keine Berechtigung'); - wp_delete_post(intval($_POST['id']), true); - wp_send_json_success('Gelöscht'); + check_ajax_referer( 'mm_team_nonce', 'nonce' ); + if ( ! current_user_can( 'delete_posts' ) ) wp_send_json_error( 'Keine Berechtigung' ); + wp_delete_post( intval( $_POST['id'] ), true ); + wp_send_json_success( 'Gelöscht' ); } -// === 4. Automatische Team-Seite === + function create_team_page_automatically() { if ( get_theme_mod( 'team_enabled', true ) && get_page_by_title( 'Team' ) == null ) { wp_insert_post( array( 'post_title' => 'Team', 'post_status' => 'publish', 'post_type' => 'page', 'post_author' => 1 ) ); @@ -1384,30 +1460,1214 @@ function create_team_page_automatically() { } add_action( 'customize_save_after', 'create_team_page_automatically' ); -// === 5. Template Loader (ROBUSTER FIX) === + function load_team_page_template( $template ) { if ( ! get_theme_mod( 'team_enabled', true ) ) return $template; - - // 1. Check auf Archiv-Seite - if ( is_post_type_archive('team_member') ) { return get_template_directory() . '/archive-team.php'; } - - // 2. Check auf Seite anhand des Slugs + if ( is_post_type_archive( 'team_member' ) ) return get_template_directory() . '/archive-team.php'; if ( is_page() ) { - // FIX: Korrekte Methode das Page-Objekt zu holen $obj = get_queried_object(); - - if ( $obj && $obj->post_name === 'team' ) { - return get_template_directory() . '/archive-team.php'; - } + if ( $obj && $obj->post_name === 'team' ) return get_template_directory() . '/archive-team.php'; } return $template; } add_filter( 'template_include', 'load_team_page_template' ); -// === 6. Customizer Settings === -add_action( 'customize_register', 'team_customize_register' ); -function team_customize_register( $wp_customize ) { - $wp_customize->add_section( 'team_settings', array( 'title' => 'Team Einstellungen', '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', 'section' => 'team_settings', 'settings' => 'team_enabled', 'type' => 'checkbox' ) ); -} \ No newline at end of file + +// Doppelte team_customize_register entfernt – ist jetzt in inc/customizer.php + +// ========================================================================= +// MENÜ-LAYOUTS: Hilfsfunktionen für header.php +// ========================================================================= + +if ( ! function_exists('mm_branding') ) : +function mm_branding( $show_title_with_logo = false ) { ?> +
+ + + +

+ +

+ + + +

+ +

+ + +
+ + + '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', + 'teamspeak' => 'fab fa-teamspeak', 'spotify' => 'fab fa-spotify', + ); ?> +
+ + +
+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' => '

', + 'after_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' ); + + +// === Announcement-Bar Höhe als CSS-Variable + Body-Klasse === +function minecraft_modern_announcement_offset_script() { + if ( ! get_option( 'mm_announcement_enabled' ) ) return; + ?> + + +
+ +
+

+

+
+
+ 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) . '

+

' . esc_html($desc_s) . '

+

' . esc_html($desc_m) . '

+
'; + + $btn_accept = ''; + $btn_select = ''; + $btn_neces = ''; + + $text_esc = wp_kses_post($text); + ?> + + + + __('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; ?> + + array( + 'name' => __( 'Videos', 'minecraft-modern-theme' ), + 'singular_name' => __( 'Video', 'minecraft-modern-theme' ), + 'add_new' => __( 'Neues Video', 'minecraft-modern-theme' ), + 'add_new_item' => __( 'Neues Video hinzufügen', 'minecraft-modern-theme' ), + 'edit_item' => __( 'Video bearbeiten', 'minecraft-modern-theme' ), + 'all_items' => __( 'Alle Videos', 'minecraft-modern-theme' ), + 'menu_name' => __( 'Videos', 'minecraft-modern-theme' ), + ), + 'public' => true, + 'has_archive' => true, + 'menu_icon' => 'dashicons-video-alt3', + 'menu_position' => 7, + 'supports' => array( 'title', 'thumbnail', 'excerpt', 'page-attributes' ), + 'rewrite' => array( 'slug' => 'videos' ), + 'show_in_rest' => true, + ) ); +} +add_action( 'init', 'mm_register_video_post_type' ); + + +// --- 2. Meta-Box: Video URL + Kategorie --- +function mm_video_meta_boxes() { + add_meta_box( + 'mm_video_data', + __( 'Video-Einstellungen', 'minecraft-modern-theme' ), + 'mm_video_meta_box_html', + 'mm_video', 'normal', 'high' + ); +} +add_action( 'add_meta_boxes', 'mm_video_meta_boxes' ); + +function mm_video_meta_box_html( $post ) { + wp_nonce_field( 'mm_video_save', 'mm_video_nonce' ); + $url = get_post_meta( $post->ID, '_mm_video_url', true ); + $category = get_post_meta( $post->ID, '_mm_video_category', true ); + $post_id = $post->ID; + ?> +
BildNameRangBildNameRang BioSort.AktionenUUID / BildSort.Aktionen
-
- 👤'; ?> +
+
+ + + + 👤 +
+ + +
+ + + +
+ +
+
+ Noch keine Mitglieder vorhanden.
Noch keine Mitglieder vorhanden.
+ + + + + + + + + + + + +
+ +

+ +

+
+ +

+
+ +
+ + +

+ +

+ +
+ Tag ausgegeben, nicht iframe + } + + return false; +} + +function mm_video_get_type( $url ) { + if ( preg_match( '/youtube\.com|youtu\.be/', $url ) ) return 'youtube'; + if ( strpos( $url, 'vimeo.com' ) !== false ) return 'vimeo'; + if ( strpos( $url, 'twitch.tv' ) !== false ) return 'twitch'; + if ( preg_match( '/\.(mp4|webm|ogv|ogg)(\?.*)?$/i', $url ) ) return 'mp4'; + return 'unknown'; +} + + +// --- 4. Embed HTML rendern --- +function mm_video_render_embed( $url, $args = array() ) { + $embed_url = mm_video_get_embed_url( $url ); + if ( ! $embed_url ) return '

' . __('Ungültige Video-URL.', 'minecraft-modern-theme') . '

'; + + $type = mm_video_get_type( $url ); + $title = isset($args['title']) ? esc_attr($args['title']) : __('Video', 'minecraft-modern-theme'); + + if ( $type === 'mp4' ) { + return '
' + . '
'; + } + + return '
' + . '
'; +} + + +// --- 5. Shortcode: [mm_video url="..."] --- +// Beispiele: +// [mm_video url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"] +// [mm_video url="https://vimeo.com/123456789" title="Mein Video"] +function mm_video_shortcode( $atts ) { + $a = shortcode_atts( array( + 'url' => '', + 'title' => __('Video', 'minecraft-modern-theme'), + ), $atts ); + + if ( empty($a['url']) ) return ''; + return mm_video_render_embed( $a['url'], $a ); +} +add_shortcode( 'mm_video', 'mm_video_shortcode' ); + + +// --- 6. Template-Loader für Video-Archiv und Galerie-Seite --- +function mm_video_template_loader( $template ) { + // Archiv (domain.de/videos/) + if ( is_post_type_archive('mm_video') ) { + $t = get_template_directory() . '/archive-video.php'; + if ( file_exists($t) ) return $t; + } + // Seite mit dem Slug "videos" + if ( is_page() ) { + $obj = get_queried_object(); + if ( $obj && $obj->post_name === 'videos' ) { + $t = get_template_directory() . '/archive-video.php'; + if ( file_exists($t) ) return $t; + } + } + return $template; +} +add_filter( 'template_include', 'mm_video_template_loader' ); + + +// --- 7. "Videos"-Seite automatisch anlegen --- +function mm_video_create_page() { + if ( ! get_page_by_path('videos') ) { + wp_insert_post( array( + 'post_title' => __('Videos', 'minecraft-modern-theme'), + 'post_name' => 'videos', + 'post_status' => 'publish', + 'post_type' => 'page', + 'post_author' => 1, + ) ); + } +} +add_action( 'after_switch_theme', 'mm_video_create_page' ); +// Auch beim Speichern im Customizer anlegen +add_action( 'customize_save_after', 'mm_video_create_page' ); + + +// ============================================================================= +// === BEWERBUNGSFORMULAR ====================================================== +// ============================================================================= + +// --- 1. Customizer: Ein/Ausschalten --- +function mm_bewerbung_customizer( $wp_customize ) { + $wp_customize->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 ), + ) ); +} +add_action( 'customize_register', 'mm_bewerbung_customizer' ); + + +// --- 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_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 ''; + foreach ( $fields as $key => $label ) { + $val = get_post_meta( $post->ID, $key, true ); + if ( ! $val ) continue; + $is_long = in_array( $key, array( '_mm_bew_warum', '_mm_bew_erfahrung' ) ); + echo ''; + echo ''; + echo ''; + } + echo '
' . esc_html($label) . ''; + if ( $is_long ) { + echo '
' . esc_html($val) . '
'; + } else { + echo '' . esc_html($val) . ''; + } + 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 ''; + $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 ''; + echo ''; +} + +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' ), + '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 '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'] ?? '' ); + + $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($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_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') ) { + $t = get_template_directory() . '/page-bewerbung.php'; + if ( file_exists($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' ); \ No newline at end of file