donau2space-wp-ki-erklaerbu.../d2s-askki/d2s-askki.php

646 lines
No EOL
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Plugin Name: Donau2Space KI-Erklärbuttons (ChatGPT, Grok, Perplexity)
* Description: Buttons unter Content oder per Shortcode. Admin-Einstellungen: Prompt, Hint-Text, Kategorie-Ausschluss, Einfügemodus, Post Types (inkl. Seiten), Styling (CSS-Variablen).
* Version: 1.4.1
* Author: Donau2Space
*/
if (!defined('ABSPATH')) exit;
define('D2S_KI_OPT_PROMPT', 'd2s_ki_prompt_prefix');
define('D2S_KI_OPT_HINT', 'd2s_ki_hint_text');
define('D2S_KI_OPT_EXCL_CATS', 'd2s_ki_excluded_category_ids');
define('D2S_KI_OPT_MODE', 'd2s_ki_insertion_mode'); // auto | shortcode | both
define('D2S_KI_OPT_POST_TYPES', 'd2s_ki_post_types'); // array of allowed post types
define('D2S_KI_OPT_STYLE', 'd2s_ki_style'); // associative array
/* =========================
* Defaults
* ========================= */
function d2s_ki_default_prompt_prefix(): string {
return 'Kannst du mir den Blogartikel ganz einfach erklären und die wichtigsten Punkte auflisten?';
}
function d2s_ki_default_hint_text(): string {
return 'Wenn du beim Lesen denkst „Worum gehts hier eigentlich genau?“ dann lass dirs von der KI in einfachen Worten erklären.';
}
function d2s_ki_default_mode(): string {
return 'auto'; // auto | shortcode | both
}
function d2s_ki_default_post_types(): array {
return ['post']; // user can add 'page' in admin
}
function d2s_ki_default_style(): array {
return [
'gpt_bg' => '#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(); ?>
<div class="d2s-ki-buttons" aria-label="Erklär-Buttons">
<?php foreach ($links as $lnk): ?>
<a
href="<?php echo esc_url($lnk['href']); ?>"
class="d2s-ki-btn d2s-ki-<?php echo esc_attr($lnk['key']); ?>"
onclick="window.open('<?php echo esc_js($lnk['href']); ?>', '_blank', 'noopener,noreferrer'); return false;"
title="<?php echo esc_attr($lnk['title']); ?>"
aria-label="<?php echo esc_attr($lnk['title']); ?>"
>
<span class="d2s-ki-icon"><?php echo esc_html($lnk['icon']); ?></span>
<span class="d2s-ki-text"><?php echo esc_html($lnk['name']); ?></span>
</a>
<?php endforeach; ?>
<?php if ($hint !== ''): ?>
<small class="d2s-ki-hint"><?php echo esc_html($hint); ?></small>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
/**
* Auto insertion: under content
*/
function d2s_ki_render_buttons($content) {
if (!is_singular()) return $content;
$post_id = (int) get_queried_object_id();
if (!d2s_ki_is_allowed_on_post($post_id, 'auto')) return $content;
return $content . d2s_ki_render_markup($post_id);
}
add_filter('the_content', 'd2s_ki_render_buttons', 20);
/**
* Shortcode: [d2s_ki_buttons]
*/
function d2s_ki_shortcode() {
if (!is_singular()) return '';
$post_id = (int) get_queried_object_id();
if (!d2s_ki_is_allowed_on_post($post_id, 'shortcode')) return '';
return d2s_ki_render_markup($post_id);
}
add_shortcode('d2s_ki_buttons', 'd2s_ki_shortcode');
/* =========================
* Assets: style.css + CSS vars
* ========================= */
function d2s_ki_enqueue_assets() {
if (!is_singular()) return;
$post_id = (int) get_queried_object_id();
$pt = get_post_type($post_id);
$allowed_pts = d2s_ki_get_post_types();
if (!$pt || !in_array($pt, $allowed_pts, true)) return;
wp_enqueue_style(
'd2s-ki-buttons',
plugin_dir_url(__FILE__) . 'assets/style.css',
[],
'1.4.1'
);
$s = d2s_ki_get_style();
$vars = [
'--d2s-gpt-bg' => $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 '<textarea name="'.esc_attr(D2S_KI_OPT_PROMPT).'" rows="3" style="width:100%;max-width:760px;">'.esc_textarea($val).'</textarea>';
echo '<p class="description">Wird an die KI übergeben. Die URL wird automatisch in einer neuen Zeile angehängt.</p>';
}
function d2s_ki_field_hint_text() {
$val = d2s_ki_get_hint_text();
echo '<textarea name="'.esc_attr(D2S_KI_OPT_HINT).'" rows="2" style="width:100%;max-width:760px;">'.esc_textarea($val).'</textarea>';
echo '<p class="description">Text unter den Buttons. Leer lassen (oder „—“) um ihn praktisch auszublenden.</p>';
}
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 '<select name="'.esc_attr(D2S_KI_OPT_MODE).'" style="min-width:360px;">';
foreach ($opts as $k => $label) {
echo '<option value="'.esc_attr($k).'" '.selected($mode, $k, false).'>'.esc_html($label).'</option>';
}
echo '</select>';
echo '<p class="description">Shortcode: <code>[d2s_ki_buttons]</code></p>';
}
function d2s_ki_field_post_types() {
$selected = d2s_ki_get_post_types();
$pts = get_post_types(['public' => true], 'objects');
echo '<div style="max-width:760px;padding:12px;border:1px solid #dcdcde;background:#fff;">';
foreach ($pts as $pt) {
if ($pt->name === 'attachment') continue;
$checked = in_array($pt->name, $selected, true) ? 'checked' : '';
echo '<label style="display:block;margin:6px 0;">';
echo '<input type="checkbox" name="'.esc_attr(D2S_KI_OPT_POST_TYPES).'[]" value="'.esc_attr($pt->name).'" '.$checked.'> ';
echo esc_html($pt->labels->singular_name) . ' <span style="opacity:.6;">(' . esc_html($pt->name) . ')</span>';
echo '</label>';
}
echo '</div>';
echo '<p class="description">Für Seiten: <strong>page</strong> aktivieren.</p>';
}
function d2s_ki_field_excluded_categories() {
$selected = d2s_ki_get_excluded_cat_ids();
$cats = get_categories(['hide_empty' => false]);
if (!$cats) {
echo '<em>Keine Kategorien gefunden.</em>';
return;
}
echo '<div style="max-width:760px;padding:12px;border:1px solid #dcdcde;background:#fff;">';
echo '<p class="description" style="margin-top:0;">Häkchen setzen = Buttons werden in dieser Kategorie <strong>nicht</strong> angezeigt (nur Posts).</p>';
foreach ($cats as $cat) {
$id = (int)$cat->term_id;
$checked = in_array($id, $selected, true) ? 'checked' : '';
echo '<label style="display:block;margin:6px 0;">';
echo '<input type="checkbox" name="'.esc_attr(D2S_KI_OPT_EXCL_CATS).'[]" value="'.esc_attr($id).'" '.$checked.'> ';
echo esc_html($cat->name) . ' <span style="opacity:.6;">(' . esc_html($cat->slug) . ')</span>';
echo '</label>';
}
echo '</div>';
}
function d2s_ki_field_style_colors() {
$s = d2s_ki_get_style();
$name = D2S_KI_OPT_STYLE;
echo '<table class="widefat striped" style="max-width:760px;"><tbody>';
$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 '<tr>';
echo '<th style="width:260px;">'.esc_html($label).'</th>';
echo '<td><input type="text" name="'.esc_attr($field).'" value="'.esc_attr($val).'" class="regular-text" placeholder="#rrggbb" /> ';
echo '<span style="display:inline-block;width:18px;height:18px;border:1px solid #ccc;vertical-align:middle;background:'.esc_attr($val).';"></span>';
echo '</td>';
echo '</tr>';
}
echo '</tbody></table>';
}
function d2s_ki_field_style_layout() {
$s = d2s_ki_get_style();
$name = D2S_KI_OPT_STYLE;
echo '<table class="widefat striped" style="max-width:760px;"><tbody>';
$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 '<tr>';
echo '<th style="width:260px;">'.esc_html($label).'</th>';
echo '<td><input type="text" name="'.esc_attr($field).'" value="'.esc_attr($val).'" class="regular-text" placeholder="'.esc_attr($hint).'" /></td>';
echo '</tr>';
}
echo '</tbody></table>';
}
function d2s_ki_field_style_fx() {
$s = d2s_ki_get_style();
$name = D2S_KI_OPT_STYLE;
echo '<table class="widefat striped" style="max-width:760px;"><tbody>';
$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 '<tr>';
echo '<th style="width:260px;">'.esc_html($label).'</th>';
echo '<td><input type="text" name="'.esc_attr($field).'" value="'.esc_attr($val).'" style="width:100%;max-width:520px;" placeholder="'.esc_attr($hint).'" /></td>';
echo '</tr>';
}
echo '</tbody></table>';
}
function d2s_ki_admin_page_render() {
if (!current_user_can('manage_options')) return;
echo '<div class="wrap">';
echo '<h1>D2S KI-Erklärbuttons</h1>';
echo '<form method="post" action="options.php">';
settings_fields('d2s_ki_buttons_settings');
do_settings_sections('d2s-ki-buttons');
submit_button('Speichern');
echo '</form>';
echo '<hr />';
echo '<h2>Info</h2>';
echo '<p><strong>Shortcode:</strong> <code>[d2s_ki_buttons]</code></p>';
echo '<p><strong>Prompt-Beispiel (Trennung):</strong><br><code>' . esc_html(d2s_ki_get_prompt_prefix()) . "\\n\\nhttps://example.com/dein-artikel/</code></p>";
echo '</div>';
}