403 ) ); } check_ajax_referer( 'advk_email_preview', 'nonce' ); $opts = self::get_options(); // Overlay the live form values that affect the design. $opts['email_logo_id'] = isset( $_POST['email_logo_id'] ) ? (int) $_POST['email_logo_id'] : 0; $opts['email_footer_text'] = isset( $_POST['email_footer_text'] ) ? sanitize_textarea_field( wp_unslash( $_POST['email_footer_text'] ) ) : ''; $opts['theme'] = isset( $_POST['theme'] ) ? sanitize_text_field( wp_unslash( $_POST['theme'] ) ) : $opts['theme']; $hex = isset( $_POST['custom_accent'] ) ? sanitize_hex_color( wp_unslash( $_POST['custom_accent'] ) ) : ''; if ( $hex ) { $opts['custom_accent'] = $hex; } $which = isset( $_POST['which'] ) ? sanitize_key( wp_unslash( $_POST['which'] ) ) : 'confirm'; $subject = isset( $_POST['subject'] ) ? sanitize_text_field( wp_unslash( $_POST['subject'] ) ) : ''; $body = isset( $_POST['body'] ) ? sanitize_textarea_field( wp_unslash( $_POST['body'] ) ) : ''; $sitename = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ); $replace = array( '{first}' => 'Maria', '{last}' => 'Muster', '{day}' => 6, '{prize}' => __( 'Wellness-Wochenende für 2', 'adventura-interactive-advent-calendar' ), '{losnr}' => 'ADV-06-4821', '{sitename}' => $sitename, ); $subject = strtr( $subject, $replace ); $body = strtr( $body, $replace ); $footer_html = ''; if ( 'reminder' === $which ) { $footer_html = '' . esc_html__( 'Keine Erinnerungen mehr erhalten', 'adventura-interactive-advent-calendar' ) . ''; } $inner = ADVK_Emails::html_wrap( $subject, $body, $opts, $footer_html ); header( 'Content-Type: text/html; charset=utf-8' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- html_wrap() escapes its inputs; this is a full document for an iframe. echo '
' . $inner . ''; wp_die(); } /** * Defaults — appearance matches the prototype's final defaults. * * @return array */ public static function defaults() { return array( // Appearance. 'theme' => 'beere', 'layout' => 'grid', 'door_style' => 'classic', 'grid_columns' => 6, 'calendar_width' => 'normal', 'credit_badge' => 0, 'winners_full_name' => 0, 'show_sponsor' => 1, 'show_prizes' => 1, 'share_enabled' => 1, 'share_image_id' => 0, 'share_image_url' => '', 'quiz_mode' => 'guided', // Effects. 'celebrate_sound' => 0, 'celebrate_melody' => 'chime', // Custom colours (used when theme = custom). 'custom_accent' => '#b4452e', 'custom_accent2' => '#2f6b4f', 'custom_bg' => '#f4ede3', 'custom_ink' => '#2a211c', // Calendar type: count, reveal logic and terminology (so the plugin // works beyond December — e.g. an Easter calendar with 10 "nests"). 'door_count' => 24, 'reveal_mode' => 'advent', // advent = December date; startdate = 1/day from start_date. 'start_date' => '', 'item_singular' => 'Türchen', 'item_plural' => 'Türchen', 'period_label' => 'Dezember', 'particles' => 'none', // none | snow // Texts / flow. 'today_override' => 12, 'year' => (int) wp_date( 'Y' ), 'eyebrow' => 'Adventura', 'title_line1' => '24 Türchen.', 'title_line2' => '24 Gewinne.', 'subtitle' => 'Jeden Tag ein neues Türchen mit einem Gewinn unserer Partner. Beantworte die Fragen und sichere dir die Teilnahme.', // Participation rules. 'prevent_duplicates' => 1, // Consent links (privacy URL defaults to the site's WP privacy page). 'privacy_url' => get_privacy_policy_url(), 'terms_url' => '', // Spam / cheat protection. 'spam_protection' => 1, 'spam_min_seconds' => 3, 'spam_rate_limit' => 15, // Cloudflare Turnstile (optional, privacy-friendly captcha). 'turnstile_enabled' => 0, 'turnstile_site_key' => '', 'turnstile_secret_key' => '', // E-mail. 'email_logo_id' => 0, 'email_footer_text' => '', 'email_enabled' => 1, 'email_from_name' => wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), 'email_from_email' => get_option( 'admin_email' ), 'email_subject' => 'Deine Teilnahme am Adventskalender (Türchen {day})', 'email_body' => "Hallo {first},\n\nvielen Dank für deine Teilnahme an Türchen {day} unseres Adventskalenders.\nDein Gewinn-Los: {prize}\n\nDeine Los-Nummer lautet: {losnr}\n\nWir drücken die Daumen!\n\nViele Grüße\n{sitename}", 'admin_notify' => 0, 'admin_email' => get_option( 'admin_email' ), // Newsletter. 'newsletter_enabled' => 0, 'newsletter_provider' => 'none', 'newsletter_api_key' => '', 'newsletter_list_id' => '', 'newsletter_double_optin' => 1, 'newsletter_label' => 'Ja, ich möchte den Newsletter erhalten.', // Reminder. 'reminder_enabled' => 0, 'reminder_double_optin' => 1, 'reminder_label' => 'Erinnere mich täglich an ein neues Türchen.', 'reminder_subject' => 'Türchen {day} ist offen! 🎁', 'reminder_body' => "Hallo {first},\n\nim Adventskalender von {sitename} ist Türchen {day} jetzt geöffnet.\nHeute wartet: {prize}\n\nViel Glück!\n{sitename}", // Referral. 'referral_enabled' => 0, // Winners. 'winner_correct_only' => 0, 'winner_email_subject' => 'Glückwunsch! Du hast bei {sitename} gewonnen 🎉', 'winner_email_body' => "Hallo {first},\n\nherzlichen Glückwunsch — du hast bei unserem Adventskalender (Türchen {day}) gewonnen!\nDein Gewinn: {prize}\nDeine Los-Nummer: {losnr}\n\nWir melden uns in Kürze mit allen Details zur Übergabe.\n\nViele Grüße\n{sitename}", // Donations (manual). A donation grants an extra lot; a donation of at // least the threshold grants a guaranteed direct-win prize. 'donation_direct_min' => 50, 'donation_direct_prize' => 'Überraschungspaket', ); } public static function get_options() { $saved = get_option( self::OPTION, array() ); if ( ! is_array( $saved ) ) { $saved = array(); } return wp_parse_args( $saved, self::defaults() ); } public function assets( $hook ) { if ( false === strpos( (string) $hook, 'advk-settings' ) ) { return; } wp_enqueue_style( 'wp-color-picker' ); wp_enqueue_script( 'wp-color-picker' ); // Init the colour pickers and notify the live preview on every change. wp_add_inline_script( 'wp-color-picker', 'jQuery(function($){var fire=function(){document.dispatchEvent(new Event("advk:preview"));};$(".advk-color").wpColorPicker({change:function(){setTimeout(fire,30);},clear:fire});});' ); wp_enqueue_style( 'advk-admin', ADVK_URL . 'assets/css/admin.css', array(), ADVK_VERSION ); // Media picker for the share image (reuses the door editor's media JS). wp_enqueue_media(); wp_enqueue_script( 'advk-admin-door', ADVK_URL . 'assets/js/admin-door.js', array( 'jquery' ), ADVK_VERSION, true ); // Live preview. wp_enqueue_script( 'advk-admin-preview', ADVK_URL . 'assets/js/admin-preview.js', array( 'jquery', 'wp-color-picker' ), ADVK_VERSION, true ); wp_localize_script( 'advk-admin-preview', 'ADVK_PREVIEW', array( 'option' => self::OPTION ) ); // E-mail preview. wp_enqueue_script( 'advk-email-preview', ADVK_URL . 'assets/js/admin-email-preview.js', array(), ADVK_VERSION, true ); wp_localize_script( 'advk-email-preview', 'ADVK_MAIL', array( 'option' => self::OPTION, 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'advk_email_preview' ), ) ); } public function add_menu() { add_submenu_page( 'advk-dashboard', __( 'Einstellungen', 'adventura-interactive-advent-calendar' ), __( 'Einstellungen', 'adventura-interactive-advent-calendar' ), 'manage_options', 'advk-settings', array( $this, 'render_page' ) ); } public function register_settings() { register_setting( 'advk_settings_group', self::OPTION, array( $this, 'sanitize' ) ); } public function sanitize( $input ) { $d = self::defaults(); $out = self::get_options(); $input = is_array( $input ) ? $input : array(); $themes = array( 'beere', 'tanne', 'amber', 'winter', 'halloween', 'ostern', 'custom' ); $out['theme'] = in_array( $input['theme'] ?? '', $themes, true ) ? $input['theme'] : $d['theme']; $count = (int) ( $input['door_count'] ?? $d['door_count'] ); $out['door_count'] = max( 1, min( 31, $count ) ); $reveal_modes = array( 'advent', 'startdate' ); $out['reveal_mode'] = in_array( $input['reveal_mode'] ?? '', $reveal_modes, true ) ? $input['reveal_mode'] : $d['reveal_mode']; $start = sanitize_text_field( $input['start_date'] ?? '' ); $out['start_date'] = preg_match( '/^\d{4}-\d{2}-\d{2}$/', $start ) ? $start : ''; $out['item_singular'] = sanitize_text_field( $input['item_singular'] ?? $d['item_singular'] ); if ( '' === $out['item_singular'] ) { $out['item_singular'] = $d['item_singular']; } $out['item_plural'] = sanitize_text_field( $input['item_plural'] ?? $d['item_plural'] ); if ( '' === $out['item_plural'] ) { $out['item_plural'] = $d['item_plural']; } $out['period_label'] = sanitize_text_field( $input['period_label'] ?? $d['period_label'] ); $particles = array( 'none', 'snow' ); $out['particles'] = in_array( $input['particles'] ?? '', $particles, true ) ? $input['particles'] : $d['particles']; $layouts = array( 'grid', 'scene' ); $out['layout'] = in_array( $input['layout'] ?? '', $layouts, true ) ? $input['layout'] : $d['layout']; $styles = array( 'classic', 'ornament', 'gift' ); $out['door_style'] = in_array( $input['door_style'] ?? '', $styles, true ) ? $input['door_style'] : $d['door_style']; $cols = (int) ( $input['grid_columns'] ?? $d['grid_columns'] ); $out['grid_columns'] = in_array( $cols, array( 3, 4, 6, 8 ), true ) ? $cols : $d['grid_columns']; $widths = array( 'compact', 'normal', 'wide', 'full' ); $out['calendar_width'] = in_array( $input['calendar_width'] ?? '', $widths, true ) ? $input['calendar_width'] : $d['calendar_width']; $out['credit_badge'] = empty( $input['credit_badge'] ) ? 0 : 1; $out['winners_full_name'] = empty( $input['winners_full_name'] ) ? 0 : 1; $out['show_sponsor'] = empty( $input['show_sponsor'] ) ? 0 : 1; $out['show_prizes'] = empty( $input['show_prizes'] ) ? 0 : 1; $out['share_enabled'] = empty( $input['share_enabled'] ) ? 0 : 1; $out['share_image_id'] = isset( $input['share_image_id'] ) ? (int) $input['share_image_id'] : 0; $out['share_image_url'] = isset( $input['share_image_url'] ) ? esc_url_raw( trim( (string) $input['share_image_url'] ) ) : ''; $modes = array( 'guided', 'single' ); $out['quiz_mode'] = in_array( $input['quiz_mode'] ?? '', $modes, true ) ? $input['quiz_mode'] : $d['quiz_mode']; $out['celebrate_sound'] = empty( $input['celebrate_sound'] ) ? 0 : 1; $melodies = array( 'chime', 'fanfare', 'bells', 'twinkle', 'arcade' ); $out['celebrate_melody'] = in_array( $input['celebrate_melody'] ?? '', $melodies, true ) ? $input['celebrate_melody'] : $d['celebrate_melody']; foreach ( array( 'custom_accent', 'custom_accent2', 'custom_bg', 'custom_ink' ) as $ck ) { $hex = sanitize_hex_color( $input[ $ck ] ?? '' ); $out[ $ck ] = $hex ? $hex : $d[ $ck ]; } $override = (int) ( $input['today_override'] ?? 0 ); $out['today_override'] = ( $override >= 0 && $override <= $out['door_count'] ) ? $override : 0; $out['year'] = (int) ( $input['year'] ?? $d['year'] ); $out['eyebrow'] = sanitize_text_field( $input['eyebrow'] ?? $d['eyebrow'] ); $out['title_line1'] = sanitize_text_field( $input['title_line1'] ?? $d['title_line1'] ); $out['title_line2'] = sanitize_text_field( $input['title_line2'] ?? $d['title_line2'] ); $out['subtitle'] = sanitize_textarea_field( $input['subtitle'] ?? $d['subtitle'] ); $out['prevent_duplicates'] = empty( $input['prevent_duplicates'] ) ? 0 : 1; $out['privacy_url'] = isset( $input['privacy_url'] ) ? esc_url_raw( trim( (string) $input['privacy_url'] ) ) : ''; $out['terms_url'] = isset( $input['terms_url'] ) ? esc_url_raw( trim( (string) $input['terms_url'] ) ) : ''; $out['spam_protection'] = empty( $input['spam_protection'] ) ? 0 : 1; $min_seconds = (int) ( $input['spam_min_seconds'] ?? $d['spam_min_seconds'] ); $out['spam_min_seconds'] = max( 0, min( 60, $min_seconds ) ); $rate = (int) ( $input['spam_rate_limit'] ?? $d['spam_rate_limit'] ); $out['spam_rate_limit'] = max( 0, min( 1000, $rate ) ); $out['turnstile_enabled'] = empty( $input['turnstile_enabled'] ) ? 0 : 1; $out['turnstile_site_key'] = sanitize_text_field( $input['turnstile_site_key'] ?? '' ); $out['turnstile_secret_key'] = sanitize_text_field( $input['turnstile_secret_key'] ?? '' ); $out['email_logo_id'] = isset( $input['email_logo_id'] ) ? (int) $input['email_logo_id'] : 0; $out['email_footer_text'] = sanitize_textarea_field( $input['email_footer_text'] ?? '' ); $out['email_enabled'] = empty( $input['email_enabled'] ) ? 0 : 1; $out['email_from_name'] = sanitize_text_field( $input['email_from_name'] ?? $d['email_from_name'] ); if ( '' === $out['email_from_name'] ) { $out['email_from_name'] = $d['email_from_name']; } $from_email = sanitize_email( $input['email_from_email'] ?? '' ); $out['email_from_email'] = is_email( $from_email ) ? $from_email : $d['email_from_email']; $out['email_subject'] = sanitize_text_field( $input['email_subject'] ?? $d['email_subject'] ); $out['email_body'] = sanitize_textarea_field( $input['email_body'] ?? $d['email_body'] ); $out['admin_notify'] = empty( $input['admin_notify'] ) ? 0 : 1; $admin_email = sanitize_email( $input['admin_email'] ?? '' ); $out['admin_email'] = is_email( $admin_email ) ? $admin_email : $d['admin_email']; // Newsletter. $out['newsletter_enabled'] = empty( $input['newsletter_enabled'] ) ? 0 : 1; $providers = array( 'none', 'mailchimp', 'brevo', 'cleverreach' ); $out['newsletter_provider'] = in_array( $input['newsletter_provider'] ?? '', $providers, true ) ? $input['newsletter_provider'] : 'none'; $out['newsletter_api_key'] = sanitize_text_field( $input['newsletter_api_key'] ?? '' ); $out['newsletter_list_id'] = sanitize_text_field( $input['newsletter_list_id'] ?? '' ); $out['newsletter_double_optin'] = empty( $input['newsletter_double_optin'] ) ? 0 : 1; $out['newsletter_label'] = sanitize_text_field( $input['newsletter_label'] ?? $d['newsletter_label'] ); // Reminder. $out['reminder_enabled'] = empty( $input['reminder_enabled'] ) ? 0 : 1; $out['reminder_double_optin'] = empty( $input['reminder_double_optin'] ) ? 0 : 1; $out['reminder_label'] = sanitize_text_field( $input['reminder_label'] ?? $d['reminder_label'] ); $out['reminder_subject'] = sanitize_text_field( $input['reminder_subject'] ?? $d['reminder_subject'] ); $out['reminder_body'] = sanitize_textarea_field( $input['reminder_body'] ?? $d['reminder_body'] ); // Referral. $out['referral_enabled'] = empty( $input['referral_enabled'] ) ? 0 : 1; $out['winner_correct_only'] = empty( $input['winner_correct_only'] ) ? 0 : 1; $out['winner_email_subject'] = sanitize_text_field( $input['winner_email_subject'] ?? $d['winner_email_subject'] ); $out['winner_email_body'] = sanitize_textarea_field( $input['winner_email_body'] ?? $d['winner_email_body'] ); $dmin = (int) ( $input['donation_direct_min'] ?? $d['donation_direct_min'] ); $out['donation_direct_min'] = max( 0, min( 100000, $dmin ) ); $out['donation_direct_prize'] = sanitize_text_field( $input['donation_direct_prize'] ?? $d['donation_direct_prize'] ); return $out; } private function name( $key ) { // Returns the raw field name; callers must escape for output (esc_attr). return self::OPTION . '[' . $key . ']'; } public function render_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } $o = self::get_options(); $theme_opts = array( 'beere' => 'Beere', 'tanne' => 'Tanne', 'amber' => 'Amber', 'winter' => 'Winter', 'halloween' => 'Halloween', 'ostern' => 'Ostern', 'custom' => 'Eigene Farben' ); $layout_opts = array( 'grid' => 'Raster', 'scene' => 'Versetzt (Szene)' ); $door_opts = array( 'classic' => 'Kachel', 'ornament' => 'Kreis', 'gift' => 'Geschenk' ); $cols_opts = array( 3 => '3 pro Reihe', 4 => '4 pro Reihe', 6 => '6 pro Reihe', 8 => '8 pro Reihe' ); $width_opts = array( 'compact' => 'Kompakt', 'normal' => 'Normal', 'wide' => 'Breit', 'full' => 'Volle Breite' ); $quiz_opts = array( 'guided' => 'Geführt (eine Frage pro Schritt)', 'single' => 'Eine Seite (alle Fragen)' ); ?>[advk_calendar]
[advk_calendar theme="tanne" layout="scene" door_style="ornament" quiz_mode="single"]
theme (beere, tanne, amber, winter, halloween, ostern, custom),
layout (grid, scene), door_style (classic, ornament, gift),
quiz_mode (guided, single).
[advk_winners]
[advk_winners day="3" limit="10"]
day ,
limit .