'#10a37f', 'gpt_fg' => '#ffffff', 'grok_bg' => '#000000', 'grok_fg' => '#ffffff', 'pplx_bg' => '#1557ff', 'pplx_fg' => '#ffffff', 'radius' => '999px', 'pad_y' => '0.65rem', 'pad_x' => '1rem', 'gap' => '0.5rem', 'shadow' => '0 6px 20px rgba(0,0,0,.12)', 'shadow_h' => '0 8px 26px rgba(0,0,0,.18)', 'scale_h' => '1.02', ]; } /* ========================= * Option getters * ========================= */ function d2s_ki_get_prompt_prefix(): string { $v = get_option(D2S_KI_OPT_PROMPT, d2s_ki_default_prompt_prefix()); $v = is_string($v) ? trim(wp_strip_all_tags($v)) : ''; return $v !== '' ? $v : d2s_ki_default_prompt_prefix(); } function d2s_ki_get_hint_text(): string { $v = get_option(D2S_KI_OPT_HINT, d2s_ki_default_hint_text()); $v = is_string($v) ? trim(wp_strip_all_tags($v)) : ''; return $v !== '' ? $v : d2s_ki_default_hint_text(); } function d2s_ki_get_excluded_cat_ids(): array { $v = get_option(D2S_KI_OPT_EXCL_CATS, []); if (!is_array($v)) return []; return array_values(array_filter(array_map('intval', $v), fn($id) => $id > 0)); } function d2s_ki_get_mode(): string { $v = get_option(D2S_KI_OPT_MODE, d2s_ki_default_mode()); $allowed = ['auto','shortcode','both']; return in_array($v, $allowed, true) ? $v : d2s_ki_default_mode(); } function d2s_ki_get_post_types(): array { $v = get_option(D2S_KI_OPT_POST_TYPES, d2s_ki_default_post_types()); if (!is_array($v)) $v = d2s_ki_default_post_types(); $v = array_values(array_filter(array_map('sanitize_key', $v))); $existing = get_post_types(['public' => true], 'names'); $v = array_values(array_filter($v, fn($pt) => isset($existing[$pt]))); return $v ?: d2s_ki_default_post_types(); } function d2s_ki_get_style(): array { $v = get_option(D2S_KI_OPT_STYLE, d2s_ki_default_style()); if (!is_array($v)) $v = []; return array_merge(d2s_ki_default_style(), $v); } /* ========================= * Logic: Should display? * ========================= */ function d2s_ki_is_allowed_on_post(int $post_id, string $context = 'auto'): bool { if (!$post_id) return false; $pt = get_post_type($post_id); if (!$pt) return false; $allowed_pts = d2s_ki_get_post_types(); if (!in_array($pt, $allowed_pts, true)) return false; if ($pt === 'post') { $excluded = d2s_ki_get_excluded_cat_ids(); if ($excluded && has_category($excluded, $post_id)) return false; } $mode = d2s_ki_get_mode(); if ($context === 'auto' && !in_array($mode, ['auto','both'], true)) return false; if ($context === 'shortcode' && !in_array($mode, ['shortcode','both'], true)) return false; return true; } /* ========================= * Prompt + Providers * ========================= */ /** * Prompt bauen: * - Promptprefix * - LEERZEILE * - URL * * Vorteil: immer sauber getrennt (kein "…?https://") */ function d2s_ki_build_prompt(string $post_url): string { $prefix = trim(d2s_ki_get_prompt_prefix()); // Falls jemand im Prefix am Ende ein Satzzeichen ohne Leerzeichen hat: egal, wir trennen fix. // 2 Zeilen sind in Chat-UIs super lesbar. return $prefix . "\n\n" . $post_url; } function d2s_ki_providers(string $prompt): array { $q = http_build_query(['q' => $prompt], '', '&', PHP_QUERY_RFC3986); return [ [ 'key' => 'chatgpt', 'name' => 'Mit ChatGPT erklären lassen', 'href' => 'https://chatgpt.com/?' . $q, 'title' => 'Öffnet ChatGPT mit vorbefüllter Nachricht', 'icon' => '💬', ], [ 'key' => 'grok', 'name' => 'Mit Grok erklären lassen', 'href' => 'https://grok.com/?' . $q, 'title' => 'Öffnet Grok mit vorbefüllter Nachricht', 'icon' => '🧠', ], [ 'key' => 'perplexity', 'name' => 'Mit Perplexity erklären lassen', 'href' => 'https://www.perplexity.ai/search?' . $q, 'title' => 'Öffnet Perplexity mit vorbefüllter Anfrage', 'icon' => '🔎', ], ]; } /* ========================= * Rendering * ========================= */ function d2s_ki_render_markup(int $post_id): string { $post_url = get_permalink($post_id); $prompt = d2s_ki_build_prompt($post_url); $links = d2s_ki_providers($prompt); $hint = d2s_ki_get_hint_text(); ob_start(); ?>
$s['gpt_bg'], '--d2s-gpt-fg' => $s['gpt_fg'], '--d2s-grok-bg' => $s['grok_bg'], '--d2s-grok-fg' => $s['grok_fg'], '--d2s-pplx-bg' => $s['pplx_bg'], '--d2s-pplx-fg' => $s['pplx_fg'], '--d2s-radius' => $s['radius'], '--d2s-pad-y' => $s['pad_y'], '--d2s-pad-x' => $s['pad_x'], '--d2s-gap' => $s['gap'], '--d2s-shadow' => $s['shadow'], '--d2s-shadow-h' => $s['shadow_h'], '--d2s-scale-h' => $s['scale_h'], ]; $css = ":root{\n"; foreach ($vars as $k => $v) { if ($v === '' || $v === null) continue; $css .= " {$k}: {$v};\n"; } $css .= "}\n"; wp_add_inline_style('d2s-ki-buttons', $css); } add_action('wp_enqueue_scripts', 'd2s_ki_enqueue_assets'); /* ========================= * Admin Settings Page * ========================= */ function d2s_ki_admin_menu() { add_options_page( 'D2S KI-Erklärbuttons', 'D2S KI-Erklärbuttons', 'manage_options', 'd2s-ki-buttons', 'd2s_ki_admin_page_render' ); } add_action('admin_menu', 'd2s_ki_admin_menu'); function d2s_ki_admin_init() { register_setting('d2s_ki_buttons_settings', D2S_KI_OPT_PROMPT, [ 'type' => 'string', 'sanitize_callback' => 'd2s_ki_sanitize_textline_required', 'default' => d2s_ki_default_prompt_prefix(), ]); register_setting('d2s_ki_buttons_settings', D2S_KI_OPT_HINT, [ 'type' => 'string', 'sanitize_callback' => 'd2s_ki_sanitize_textline_required', 'default' => d2s_ki_default_hint_text(), ]); register_setting('d2s_ki_buttons_settings', D2S_KI_OPT_EXCL_CATS, [ 'type' => 'array', 'sanitize_callback' => 'd2s_ki_sanitize_excluded_categories', 'default' => [], ]); register_setting('d2s_ki_buttons_settings', D2S_KI_OPT_MODE, [ 'type' => 'string', 'sanitize_callback' => 'd2s_ki_sanitize_mode', 'default' => d2s_ki_default_mode(), ]); register_setting('d2s_ki_buttons_settings', D2S_KI_OPT_POST_TYPES, [ 'type' => 'array', 'sanitize_callback' => 'd2s_ki_sanitize_post_types', 'default' => d2s_ki_default_post_types(), ]); register_setting('d2s_ki_buttons_settings', D2S_KI_OPT_STYLE, [ 'type' => 'array', 'sanitize_callback' => 'd2s_ki_sanitize_style', 'default' => d2s_ki_default_style(), ]); add_settings_section( 'd2s_ki_main', 'Allgemein', '__return_false', 'd2s-ki-buttons' ); add_settings_field( 'd2s_ki_prompt_prefix', 'Prompt-Text (Prefix)', 'd2s_ki_field_prompt_prefix', 'd2s-ki-buttons', 'd2s_ki_main' ); add_settings_field( 'd2s_ki_hint_text', 'Hint-Text unter den Buttons', 'd2s_ki_field_hint_text', 'd2s-ki-buttons', 'd2s_ki_main' ); add_settings_field( 'd2s_ki_mode', 'Einfüge-Modus', 'd2s_ki_field_mode', 'd2s-ki-buttons', 'd2s_ki_main' ); add_settings_field( 'd2s_ki_post_types', 'Anzeigen auf', 'd2s_ki_field_post_types', 'd2s-ki-buttons', 'd2s_ki_main' ); add_settings_field( 'd2s_ki_excluded_cats', 'Kategorien ausschließen (nur Posts)', 'd2s_ki_field_excluded_categories', 'd2s-ki-buttons', 'd2s_ki_main' ); add_settings_section( 'd2s_ki_style', 'Styling', '__return_false', 'd2s-ki-buttons' ); add_settings_field( 'd2s_ki_style_colors', 'Farben', 'd2s_ki_field_style_colors', 'd2s-ki-buttons', 'd2s_ki_style' ); add_settings_field( 'd2s_ki_style_layout', 'Layout', 'd2s_ki_field_style_layout', 'd2s-ki-buttons', 'd2s_ki_style' ); add_settings_field( 'd2s_ki_style_fx', 'Effekte', 'd2s_ki_field_style_fx', 'd2s-ki-buttons', 'd2s_ki_style' ); } add_action('admin_init', 'd2s_ki_admin_init'); /* ===== Sanitizers ===== */ function d2s_ki_sanitize_textline_required($v): string { if (!is_string($v)) $v = ''; $v = trim(wp_strip_all_tags($v)); return $v !== '' ? $v : '—'; } function d2s_ki_sanitize_excluded_categories($v): array { if (!is_array($v)) return []; return array_values(array_unique(array_filter(array_map('intval', $v), fn($id) => $id > 0))); } function d2s_ki_sanitize_mode($v): string { $allowed = ['auto','shortcode','both']; return in_array($v, $allowed, true) ? $v : d2s_ki_default_mode(); } function d2s_ki_sanitize_post_types($v): array { if (!is_array($v)) $v = []; $v = array_values(array_filter(array_map('sanitize_key', $v))); $existing = get_post_types(['public' => true], 'names'); $v = array_values(array_filter($v, fn($pt) => isset($existing[$pt]))); return $v ?: d2s_ki_default_post_types(); } function d2s_ki_sanitize_hex_color_or_empty($v): string { $v = is_string($v) ? trim($v) : ''; if ($v === '') return ''; $c = sanitize_hex_color($v); return $c ? $c : ''; } function d2s_ki_sanitize_css_len($v, string $fallback): string { $v = is_string($v) ? trim($v) : ''; if ($v === '') return $fallback; if (preg_match('/^[0-9.\s%a-zA-Z()+,-]+$/', $v)) return $v; return $fallback; } function d2s_ki_sanitize_css_value($v, string $fallback): string { $v = is_string($v) ? trim($v) : ''; if ($v === '') return $fallback; if (preg_match('/^[0-9.\s%a-zA-Z()+,\/-]+$/', $v)) return $v; return $fallback; } function d2s_ki_sanitize_style($v): array { $d = d2s_ki_default_style(); if (!is_array($v)) $v = []; return [ 'gpt_bg' => d2s_ki_sanitize_hex_color_or_empty($v['gpt_bg'] ?? $d['gpt_bg']) ?: $d['gpt_bg'], 'gpt_fg' => d2s_ki_sanitize_hex_color_or_empty($v['gpt_fg'] ?? $d['gpt_fg']) ?: $d['gpt_fg'], 'grok_bg' => d2s_ki_sanitize_hex_color_or_empty($v['grok_bg'] ?? $d['grok_bg']) ?: $d['grok_bg'], 'grok_fg' => d2s_ki_sanitize_hex_color_or_empty($v['grok_fg'] ?? $d['grok_fg']) ?: $d['grok_fg'], 'pplx_bg' => d2s_ki_sanitize_hex_color_or_empty($v['pplx_bg'] ?? $d['pplx_bg']) ?: $d['pplx_bg'], 'pplx_fg' => d2s_ki_sanitize_hex_color_or_empty($v['pplx_fg'] ?? $d['pplx_fg']) ?: $d['pplx_fg'], 'radius' => d2s_ki_sanitize_css_len($v['radius'] ?? '', $d['radius']), 'pad_y' => d2s_ki_sanitize_css_len($v['pad_y'] ?? '', $d['pad_y']), 'pad_x' => d2s_ki_sanitize_css_len($v['pad_x'] ?? '', $d['pad_x']), 'gap' => d2s_ki_sanitize_css_len($v['gap'] ?? '', $d['gap']), 'shadow' => d2s_ki_sanitize_css_value($v['shadow'] ?? '', $d['shadow']), 'shadow_h' => d2s_ki_sanitize_css_value($v['shadow_h'] ?? '', $d['shadow_h']), 'scale_h' => d2s_ki_sanitize_css_value($v['scale_h'] ?? '', $d['scale_h']), ]; } /* ===== Admin Fields ===== */ function d2s_ki_field_prompt_prefix() { $val = d2s_ki_get_prompt_prefix(); echo ''; echo '

Wird an die KI übergeben. Die URL wird automatisch in einer neuen Zeile angehängt.

'; } function d2s_ki_field_hint_text() { $val = d2s_ki_get_hint_text(); echo ''; echo '

Text unter den Buttons. Leer lassen (oder „—“) um ihn praktisch auszublenden.

'; } function d2s_ki_field_mode() { $mode = d2s_ki_get_mode(); $opts = [ 'auto' => 'Automatisch unter Content einfügen', 'shortcode' => 'Nur per Shortcode (du platzierst es selbst)', 'both' => 'Beides (Auto + Shortcode)', ]; echo ''; echo '

Shortcode: [d2s_ki_buttons]

'; } function d2s_ki_field_post_types() { $selected = d2s_ki_get_post_types(); $pts = get_post_types(['public' => true], 'objects'); echo '
'; foreach ($pts as $pt) { if ($pt->name === 'attachment') continue; $checked = in_array($pt->name, $selected, true) ? 'checked' : ''; echo ''; } echo '
'; echo '

Für Seiten: page aktivieren.

'; } function d2s_ki_field_excluded_categories() { $selected = d2s_ki_get_excluded_cat_ids(); $cats = get_categories(['hide_empty' => false]); if (!$cats) { echo 'Keine Kategorien gefunden.'; return; } echo '
'; echo '

Häkchen setzen = Buttons werden in dieser Kategorie nicht angezeigt (nur Posts).

'; foreach ($cats as $cat) { $id = (int)$cat->term_id; $checked = in_array($id, $selected, true) ? 'checked' : ''; echo ''; } echo '
'; } function d2s_ki_field_style_colors() { $s = d2s_ki_get_style(); $name = D2S_KI_OPT_STYLE; echo ''; $rows = [ ['ChatGPT Hintergrund', "{$name}[gpt_bg]", $s['gpt_bg']], ['ChatGPT Text', "{$name}[gpt_fg]", $s['gpt_fg']], ['Grok Hintergrund', "{$name}[grok_bg]", $s['grok_bg']], ['Grok Text', "{$name}[grok_fg]", $s['grok_fg']], ['Perplexity Hintergrund', "{$name}[pplx_bg]", $s['pplx_bg']], ['Perplexity Text', "{$name}[pplx_fg]", $s['pplx_fg']], ]; foreach ($rows as [$label, $field, $val]) { echo ''; echo ''; echo ''; echo ''; } echo '
'.esc_html($label).' '; echo ''; echo '
'; } function d2s_ki_field_style_layout() { $s = d2s_ki_get_style(); $name = D2S_KI_OPT_STYLE; echo ''; $rows = [ ['Border-Radius', "{$name}[radius]", $s['radius'], 'z.B. 999px / 14px'], ['Padding Y', "{$name}[pad_y]", $s['pad_y'], 'z.B. 0.65rem'], ['Padding X', "{$name}[pad_x]", $s['pad_x'], 'z.B. 1rem'], ['Gap', "{$name}[gap]", $s['gap'], 'z.B. 0.5rem'], ]; foreach ($rows as [$label, $field, $val, $hint]) { echo ''; echo ''; echo ''; echo ''; } echo '
'.esc_html($label).'
'; } function d2s_ki_field_style_fx() { $s = d2s_ki_get_style(); $name = D2S_KI_OPT_STYLE; echo ''; $rows = [ ['Shadow', "{$name}[shadow]", $s['shadow'], 'z.B. 0 6px 20px rgba(0,0,0,.12)'], ['Shadow Hover', "{$name}[shadow_h]", $s['shadow_h'], 'z.B. 0 8px 26px rgba(0,0,0,.18)'], ['Scale Hover', "{$name}[scale_h]", $s['scale_h'], 'z.B. 1.02'], ]; foreach ($rows as [$label, $field, $val, $hint]) { echo ''; echo ''; echo ''; echo ''; } echo '
'.esc_html($label).'
'; } function d2s_ki_admin_page_render() { if (!current_user_can('manage_options')) return; echo '
'; echo '

D2S KI-Erklärbuttons

'; echo '
'; settings_fields('d2s_ki_buttons_settings'); do_settings_sections('d2s-ki-buttons'); submit_button('Speichern'); echo '
'; echo '
'; echo '

Info

'; echo '

Shortcode: [d2s_ki_buttons]

'; echo '

Prompt-Beispiel (Trennung):
' . esc_html(d2s_ki_get_prompt_prefix()) . "\\n\\nhttps://example.com/dein-artikel/

"; echo '
'; }